前言

在2017年Google I/O大会上,Kotlin正式成为Android开发的一等语言,两年时间里,Google的文档演示代码几乎都已经换成了Kotlin,之前对Kotlin也就是了解,写过一些demo,并没有实际用到项目中去,最近的一个项目,下定决心完完全全用Kotlin来写,这里结合实际项目,记录一些Kotlin写起来很方便的代码。

官方学习文档地址

延迟初始化

Kotlin 对于属性还是很严格的,如果不进行延迟初始化的话,必须要在声明的同时进行初始化。

  • val 使用 by lazy {}

    延迟初始化需要使用 by lazy 来进行委托延迟初始化,这样变量在使用的时候才会进行初始化。我在项目中常用的在Activity中声明的Fragment。

    1
    2
    private val mAFragment: AFragment by lazy { AFragment() }
    private val mBFragment: BFragment by lazy { BFragment() }

    个人的理解用Java来表示就是

    1
    2
    3
    4
    5
    6
    7
    8
    private final AFragment mAfragment;

    void use(){
    if(mAfragment == null){
    mAfragment = new AFragment()
    }
    }

  • var 使用 lateinit

    前面的by lazy 只能用于val属性,对于var只能使用lateinit修饰,其实lateinit并没有帮你初始化,只是抑制编译器警告而已,需要自己确保变量在使用之前初始化过,不然还是会报错。

    1
    private lateinit var name:String

作用域函数

作用域函数为属性提供了一个单独的代码块,极大地方便属性的操作,下面是演示代码。

常用的有(also,apply)、 ( let,run) 、 with

  • also apply对属性进行操作并返回原属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //都返回原属性
    fun testAlsoApply() {

    //also内部用it
    val also = "ALSO".also {
    println(it.replace("A", "B"))//BLSO
    }
    println(also)//ALSO

    //apply内部用this
    val apply = "APPLY".apply {
    println(this.replace("A", "B"))//BPPLY
    }
    println(apply)//APPLY

    }

    这两个在Android项目中用到的地方还是比较多的,比如在Fragment中的newInstance()使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    companion object {

    private const val ROOM_TYPE = "TAG_TYPE"
    private const val ROOM_TYPE2 = "TYPE2"

    fun newInstance(type: Int = 0, smType: Int = 0): AFragment {
    return AFragment().also {
    val bundle = Bundle()
    bundle.putInt(ROOM_TYPE, type)
    bundle.putInt(ROOM_TYPE2, smType)
    it.arguments = bundle
    }
    }

    }

    这里的 companion object 是Kotlin中的半生函数,类似于Java的静态内部类,上面的代码实现的是一个Framgnet的静态方法newInstance,这里用 also 作用域函数进行对Fragment的arguments赋值操作,并返回生成的Fragment。

  • let run 对属性进行操作,返回任意新属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //都返回最后一行的属性值
    fun testLetRun() {

    //let使用it
    val let = "LET".let {
    println(it)//LET
    it.toLowerCase()//let变成"let"
    //println(it)//这样返回的就是Unit
    }
    println(let)//ALSO
    //run内部用this
    val run = "RUN".run {
    println(this)
    this.toLowerCase()
    }
    println(run)//APPLY

    }
  • with 对属性直接进行操作,方便一些需要统一设置属性的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //输出结果
    //User(name=name, age=18)
    //User(name=with, age=19)
    fun testWith() {
    val user = User("name", 18)
    println(user)
    with(user) {
    name = "with"
    age = 19
    }
    println(user)
    }

静态方法(不太方便)

Kotlin中的静态方法写起来真的就不如Java了,需要使用伴生对象来写。

1
2
3
4
5
6
7
8
9
10
11
12
class AFragment{
companion object {
private const val TAG = "TAG"
fun newInstance(tag: Int): AFragment {
return AFragment().also {
val bundle = Bundle()
bundle.putInt(TAG, tag)
it.arguments = bundle
}
}
}
}

More Coming Soon