欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android开发学习之路--Kotlin之Android开发使用心得和注意事项

程序员文章站 2022-03-23 20:57:15
前言 1 @autowired需要@jvmfield注解 我们在activity的oncreate中就可以直接这么写 tv1.text = "hello ko...

前言

1 @autowired需要@jvmfield注解




    

我们在activity的oncreate中就可以直接这么写

tv1.text = "hello kotlin" //textview填内容
bt1.setonclicklistener {  //监听button事件
    toast("hello kotlin")
}

但是如果是fragment中的话,需要注意一点就是:

不能在oncreateview方法里用view,不然会出现空指针异常,需要在onviewcreate里。因为kotlin的插件用了getview来findviewbyid,在onviewcreate后才获取到view.

3 with,apply

减少代码量,这个可以看下上一篇《 android开发学习之路–kotlin之常用表达式及函数》,这里不做过多介绍

4 fun内部也可以定义fun 利用局部函数抽取重复代码

可以在函数内部定义函数,来简化代码

比如一个findview的函数如下:

fun initview() {
    private var mtv1:textview = itemview.findviewbyid(r.id.tv_1) as textview
    private var mtv2:textview = itemview.findviewbyid(r.id.tv_2) as textview
    private var mtv3:textview = itemview.findviewbyid(r.id.tv_3) as textview
}

我们可以写一个内部函数,然后可以简化如下:

fun initview() {
    private fun findtextview(id: int) = itemview.findviewbyid(id) as textview

    private var mtv1 = findtextview(r.id.tv_1)
    private var mtv2 = findtextview(r.id.tv_2)
    private var mtv3 = findtextview(r.id.tv_3)
}

5 匿名内部类

kotlin中没有java的new关键字,所以在调用类似于监听的方法中的匿名内部类时候,需要用到object,如下所示

addontabselectedlistener(object : tablayout.ontabselectedlistener {
    override fun ontabreselected(tab: tablayout.tab?) {
    }

    override fun ontabunselected(tab: tablayout.tab?) {

    }

    override fun ontabselected(tab: tablayout.tab?) {

    }
})

6 代码注入 kapt

编译器的依赖关系需要使用kapt

kapt "com.google.dagger:dagger-compiler:$dagger_compiler_version"

7 static方法

在kotlin中使用类似java的静态方法,使用companion object

class utils {
    companion object {
        fun test() {
            toast("hello kotlin")
        }
    }
}

上述可以使用utils.test()来调用

8 单表达式函数

a+b,或者比大小的函数,可以写的很简单:

fun sum(a:int, b:int) = a+b 

9 使用数据类来快速实现model类

一般java中我们声明一个model类,需要设置属性为private,然后实现set/get方法,而kotlin中,我们只要简单地使用data就可以了。

//用data关键词来声明一个数据类,除了会自动实现get set,还会自动生成equals hashcode tostring
data class person(
    var name:string = "",
    var sex:string = "male"
)

若要实现parcelable,需要在builder.gradle中加入plugin

apply plugin: 'kotlin-android-extensions'

......

androidextensions {
    experimental = true
}

具体注解如下:

@parcelize
data class person(
    var name:string = "",
    var sex:string = "male"
): parcelable

10 lambda表达式简化onclicklistener

比如一个click事件
textview textview = new textview(context);
textview.setonclicklistener(new view.onclicklistener() {
    @override
    public void onclick(view v) {
        //do something
    }
});
lambda的方式
textview.setonclicklistener({ v ->
    {
        //do something
    }
})
当lambda的参数没有使用时可以省略,省略的时候用it来替代
textview.setonclicklistener({ 
    //do something
})
函数如果没有其他参数可以省略,最后变成了
textview.setonclicklistener {
   //do something 
}

11 高阶函数+lambda简化代码

当我们监听tablayout的select的时候,一般我们这么写:

tablayout.addontabselectedlistener(object : tablayout.ontabselectedlistener {
    override fun ontabreselected(tab: tablayout.tab?) {
         //do something
    }

    override fun ontabunselected(tab: tablayout.tab?) {
        //do something
    }

    override fun ontabselected(tab: tablayout.tab?) {
        //do something
    }
})

有时候我们只需要调用其中的一个方法,则显得代码臃肿。这个时候高阶函数和lambda就可以派上用场了。

首先我们实现一个类实现tablayout.ontabselectedlistener接口。然后定义三个函数,传入的参数分别是函数,然后当接口中的方法被回调后,再调用具体传入的函数的方法。

class _ontabselectedlistener : tablayout.ontabselectedlistener {
    private var _ontabreselected: ((tab: tablayout.tab?) -> unit)? = null
    private var _ontabunselected: ((tab: tablayout.tab?) -> unit)? = null
    private var _ontabselected: ((tab: tablayout.tab?) -> unit)? = null

    override fun ontabreselected(tab: tablayout.tab?) {
        _ontabreselected?.invoke(tab)
    }

    fun ontabreselected(func: (tab: tablayout.tab?) -> unit) {
        _ontabreselected = func
    }

    override fun ontabunselected(tab: tablayout.tab?) {
        _ontabunselected?.invoke(tab)
    }

    fun ontabunselected(func: (tab: tablayout.tab?) -> unit) {
        _ontabunselected = func
    }

    override fun ontabselected(tab: tablayout.tab?) {
        _ontabselected?.invoke(tab)
    }

    fun ontabselected(func: (tab: tablayout.tab?) -> unit) {
        _ontabselected = func
    }
}

然后我们写一个tablayout的扩展函数,入参是一个函数,是我们上面写好的这个类的函数,返回一个unit

fun tablayout.addontabselectedlistener(func: _ontabselectedlistener.() -> unit) {
    val listener = _ontabselectedlistener()
    listener.func()
    addontabselectedlistener(listener)
}

最后我们可以把代码写成这样:

addontabselectedlistener {
    ontabunselected {
        //do something
    }

    ontabselected {
        //do something
    }

    ontabreselected { 
        //do something
    }
}

当然,可以省略ontabunselected, ontabselected,ontabreselected的任何一个或者全部。

12 委托模式(by 关键字)

先定义两个接口base1和base2
interface base1 {
    fun print1()
}
interface base2 {
    fun print2()
}
两个实现类分别实现base1和base2
class baseimpl(val x: int) : base1 {
    override fun print1() {
        log.d("baseimpl", "print1 -> $x")
    }
}
class baseimpl2(val x: int) : base2 {
    override fun print2() {
        log.d("baseimpl", "print2 -> $x")
    }
}
接着用代理
class printtest(
        b1: base1,
        b2: base2
) : base1 by b1, base2 by b2
具体实现
val print1 = baseimpl(10)
val print2 = baseimpl2(5)
printtest(print1, print2).print1()
printtest(print1, print2).print2()

// 输出
d/baseimpl: print1 -> 10
d/baseimpl: print2 -> 5

printertest没有实现接口base1的方法print1(),而是通过关键字by,将实现委托给了b1。