都掌握了吗?Kotlin技能小成,技能掌握


前些文章描述了 Kotlin教程,包括一些基本语法。
很多时候,还需要加以练习。
本文将开发过程中,遇到的点,整理成线,继而到面
希望 把下面的问题掌握之后,掌握Kotlin在Android中的开发能力

一眼望去,立刻知道答案,Kotlin小成

1️⃣实现findViewById有几种方式?

方法一:可以更低成本从java转kotlin

@BindView(R2.id.acco_refresh_layout)
lateinit var mSmartRefreshLayout: SmartRefreshLayout

沿用ButterKnifer,可以减少从Java转Kotin的代码转换工作量。

进阶思考:为什么用lateinit?不用行不行?

方法二:使用Kotlin自带的findViewById

import kotlinx.android.synthetic.main.这里是layout的xml名字.*

acco_ll_service_info!!.visibility = View.GONE

Kotlin自带findViewById功能,acco_ll_service_info就是view在layout中的id。可以通过id直接访问。

进阶思考:Kotlin中的findViewById源码分析?

方法三:使用Android自带的findViewById

第一种写法,去掉泛型,在前面声明该控件的类型
var sml1 : SmartRefreshLayout = findViewById(R.id.acco_refresh_layout)

第二种写法,在泛型中指定该控件类型
var sml2 = findViewById<SmartRefreshLayout>(R.id.acco_refresh_layout)

这两者写法得到的sml1和sml2是一样的


2️⃣根据状态改变初始值?

lateinit var mCachedProfileBean: UserInfoResponse.DataBean

private val tradePwdStatus: String
    get() = if (mCachedProfileBean?.tradePasswordStatus == UserInfoResponse.DataBean.TRADE_PWD_UN_SET) {
        "未设置"
    } else ""

val变量tradePwdStatus会根据mCachedProfileBean动态的改变 返回值

进阶思考:mCachedProfileBean未初始化就被访问会发生什么?

3️⃣怎么定义public static final 常量?

companion object {
    private const val MSG_EXIT_APP = 1
}

这里定义了int MSG_EXIT_APP。需要放在 companion object中。

进阶思考①:伴生对象companion object适用范围,特点是什么?
进阶思考②:const与val的区别?const相当于什么?跟@JvmField的效果比较

4️⃣?. 与!!.的区别是 什么

?.表示当前对象如果为空,则返回null。

fun main() {
    var numbers : List<String>?= null
    println(numbers?.size?:999)     //输出999
}

这个例子当numbers为null,则打印999,否则,输出numbers的size。

!!.表示当前对象为空,也继续该行语句的执行,然后会抛出NPE

fun main() {
    var numbers : List<String>?= null
    println(numbers!!.size?:999)     //输出999
}

这个范例:会抛出KotlinNullPointerException


5️⃣lateinit标记的变量,若没初始化怎么处理?

if (!this::mCachedProfileBean.isInitialized) {
    doSomething()
    return
}

mCachedProfileBean需要通过this::来进行引用。

如果这个判断在内部类。还需要指定this的引用对象

if (!this@SettingsActivity::mCachedProfileBean.isInitialized) {}

lateinit跟isInitialized是 配对出现的。

变量通过lateinit标记,有初始化,可以正常使用;

没有初始化,则通过isInitialized进行判断。

通过lateinit标记的变量,在使用的时候,就需要注意其初始化状态
private val tradePwdStatus: String
        get() = if (this::mCachedProfileBean.isInitialized
                    && mCachedProfileBean.tradePasswordStatus == UserInfoResponse.DataBean.TRADE_PWD_UN_SET) {
            "未设置"
        } else ""

没加this::mCachedProfileBean.isInitialized,IDE也不会提示什么。

万一,你一个不留神,就可能会抛出kotlin.UninitializedPropertyAccessException


6️⃣内部类的使用

private inner class MyHandler(activity: Activity) : Handler() {
    var mWeakReference: WeakReference<Activity> = WeakReference(activity)

    override fun handleMessage(msg: Message) {
        doSomething()
        finish()
    }
}

MyHandler继承自Handler,实现了handleMessage。

这里是通过inner来实现。假如我不用inner标记会如何?

inner内部类,隐式持有外部类的引用,可以访问外部类成员属性和成员函数。
若没有inner标记,则无法访问成员属性和成员函数。

在Kotlin的某个类中,写private class跟,新建了一个文件的效果是一样的。


7️⃣如何写一个instance函数

companion object {
    fun instance(): FundsOfflineRechargeFragment {
        return FundsOfflineRechargeFragment()
     }
}
调用方式:
FundsOfflineRechargeFragment.instance()

8️⃣集合的创建方式

集合有3种:List、Set、Map。整理了一下,主要是这些

  • List:建、增、删、查、改、排序
    建:listOf
    增:add、addAll
    删:removeAt
    查:indexOf、lastIndexOf、indexOfFirst、indexOfLast、binarySearch、
    改:set、fill
    排序:sort、sortDescending、sortBy、sortByDescending、sortWith、shuffle、reverse
  • Set:建、合并、求同、取异
    建:setOf
    合并:union
    求同:intersect
    取异:subtract
  • Map:建、增、删、查、改、过滤
    建:mapOf
    增:plus(有改的效果)、+、put、putAll、plusAssign
    删:minus(有改的效果)、-、remove
    查:get、getOrElse、getOrDefault
    改:put、putAll
    过滤:filter

9️⃣主构造函数什么时候需要显式的写?

class ViewHolder internal constructor(itemView : View): RecyclerView.ViewHolder(itemView) {
    @BindView(R2.id.acco_iv_icon)
    lateinit var mIconIv : ImageView
    @BindView(R2.id.acco_tv_name)
    lateinit var mNameTv : TextView

    init {
        ButterKnife.bind(this, itemView)
    }
}

构造函数有注解或可见性修饰符。就需要显式的写。

初始化的代码需要放在init{}中
进阶思考:初始化能否有多个init代码块?类的初始化顺序是怎么样的?
private inner class MergeObservable(response1: BankCardListResponse, response2: UserAccountResponse) : Merge2Response<BankCardListResponse, UserAccountResponse>(response1, response2)

这里省略了 constructor

这是一个名为MergeObservable的内部类,有两个参数。

这相当于java的
private class MergeObservable extends Merge2Response<BankCardListResponse, UserAccountResponse> {
   public MergeObservable(BankCardListResponse response1, UserAccountResponse response2) {
        super(response1, response2);
    }
}

主构函数response1、response2代表了两个参数。

后面的<BankCardListResponse, UserAccountResponse>(response1, response2),都是给父类Merge2Response的。

泛型定义传了BankCardListResponse, UserAccountResponse
参数传了response1, response2


相关内容

    暂无相关文章