Android开发学习之路--Kotlin之Android开发使用心得和注意事项
前言
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和base2interface 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。
推荐阅读
-
Android开发学习之控件GridView的使用讲解
-
Android开发笔记之 RecyclerView和ScrollView嵌套使用,ListView和ScrollView嵌套使用对比
-
Android开发指南之Kotlin使用技巧
-
Android开发之ExoPlayer的学习和使用(音频)讲解
-
Android开发之android架构学习和使用
-
Android开发学习 之 三、Log,DDMS和AVD
-
Android开发之Kotlin使用指南
-
Android开发学习之路--Kotlin之Android开发使用心得和注意事项
-
android开发程序之路(列表视图 ListView和GridView使用)
-
Android开发学习之控件GridView的使用讲解