Kotlin Android 扩展

背景

相信每一位安卓开发人员对 findViewById() 这个方法再熟悉不过了,毫无疑问,潜在的 bug 和脏乱的代码令后续开发无从下手的。 尽管存在一系列的开源库能够为这个问题带来解决方案,然而对于运行时依赖的库,需要为每一个 View 注解变量字段。

现在 Kotlin 安卓扩展插件能够提供与这些开源库功能相同的体验,不需要添加任何额外代码,也不影响任何运行时体验。
因此,我们可以写出如下代码:

// 使用来自主代码集的 R.layout.activity_main
import kotlinx.android.synthetic.main.activity_main.*

class MyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        textView.setText("Hello, world!")
        // 而不是 findViewById(R.id.textView) as TextView
    }
}

textView 是对 Activity 的一项扩展属性,与在 activity_main.xml 中的声明具有同样类型。

使用 Kotlin 安卓扩展

依赖配置
安卓扩展是 Kotlin IDEA 插件的组成之一,因此不需要再单独安装额外插件。
开发者仅需要在模块的 build.gradle文件中启用 Gradle 安卓扩展插件即可:

apply plugin: 'kotlin-android-extensions'

导入合成属性
仅需要一行即可非常方便导入指定布局文件中所有控件属性:

import kotlinx.android.synthetic.main.<布局>.*

假设当前布局文件是 activity_main.xml,我们只需要引入

kotlinx.android.synthetic.main.activity_main.*

若需要调用 View 的合成属性(在适配器类中非常有用),同时还应该导入

 kotlinx.android.synthetic.main.activity_main.view.*

导入完成后即可调用在xml文件中以视图控件命名属性的对应扩展, 比如下例:

 

将有一个名为 hello 的属性:

activity.hello.setText("Hi!")

安卓多渠道
安卓扩展插件现已支持安卓多渠道。假设当前在 build.gradle
文件中指定一个名为 free 的渠道:

android {
    productFlavors {
        free {
            versionName "1.0-free"
        }
    }
}

所以现在只需要添加一行导入语句即可从 free/res/layout/activity_free.xml
布局中导入所有的合成属性:

import kotlinx.android.synthetic.free.activity_free.*

背后原理

Kotlin 安卓扩展作为 Kotlin 编译器的插件,主要有两大作用:

  1. 在每一个 KotlinActivity 中添加一个隐藏缓存函数以及一个变量。该方法非常简洁,因此不会直接对APK体积有明显增加。
  2. 使用函数调用替换每一个合成属性。
    其工作原理是,当调用合成属性,在模块资源中 Kotlin Activity/Fragment 类作为接收器时,缓存函数将被调用。
    例如:
class MyActivity : Activity()
fun MyActivity.a() { 
    this.textView.setText(“”)
}

在 MyActivity 中生成一个隐藏缓存函数,因此我们可以使用缓存机制。

然而在下面的例子中:

fun Activity.b() { 
    this.textView.setText(“”)
}

我们并不知道这个函数会被我们自己的来源或者普通的 Java Activity 调用,因此, 即便在前一个示例中的 MyActivity 是接收器,也不会使用缓存。

你可能感兴趣的:(Kotlin Android 扩展)