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开发使用心得和注意事项的主要内容,如果未能解决你的问题,请参考以下文章

Android开发学习之路--Kotlin之常用表达式及函数

Android开发学习之路--Kotlin之类及对象

Android开发学习之路--UI之基本布局

Android开发学习之路--UI之ListView

Android开发学习之路--UI之简单聊天界面

Android开发学习之路--RxAndroid之lambda