前言

在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
    
    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
    
    //都返回原属性
    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
            }
        }
    }
}