Android开发学习之路--Kotlin之Android开发使用心得和注意事项
Posted 东月之神
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android开发学习之路--Kotlin之Android开发使用心得和注意事项相关的知识,希望对你有一定的参考价值。
前言
1 @Autowired需要@JvmField注解
@Autowired(name = "test")
@JvmField
var currentDate: Long = 0
当我们用到类似于阿里的ARouter的时候,会发现@Autowired不起作用,其实是注入代码为了减少反射,使用的字段赋值的方式来注入的,Kotlin 默认会生成 set/get 方法,并把属性设置为 private。这时就可以使用 @JvmField 注解,编译之后该属性将直接暴露。
2 不用写findViewById
先看一个布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/bt1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
我们在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
以上是关于Android开发学习之路--Kotlin之Android开发使用心得和注意事项的主要内容,如果未能解决你的问题,请参考以下文章