接上篇,整理一下Kotlin在Android平台上应用的一些实例及方法。

Kotlin Android Extensions

Kotlin针对Android提供了Kotlin Android Extensions,可以很大程度上增强Android的开发体验。
背景
相信每个Android开发人员都很清楚findViewById()函数,并且备受摧残,毫无疑问,大量的findViewById()会造成代码阅读上的干扰和错误定位的难度,虽然有类似Butterknife之类的库可以通过注解实现绑定,但在实际使用过程中还是要为每个变量增加注解,倘若出现大量注解,维护难度应该不亚于直接编码,而其优点无非是代码看起来简洁了,但整体看似乎并不是特别优雅,且需要增加额外的运行库。

现在,Kotlin Android Extensions插件给我们提供了更优雅的方法,且不需要额外引入运行库,比如,我们的代码可以像下面这样写:

// Using R.layout.activity_main from the main source set
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!")
        // Instead of findViewById(R.id.textView) as TextView
    }
}

其中,textView是Activity的一个扩展属性,它的类型与activity_main.xml中资源id类型相同。
使用Kotlin Android扩展
1、配置依赖关系

Android扩展程序是Kotlin IDEA插件的一部分,所以你不需要安装其他插件,只需在需要的时候在项目本地build.gradle文件中启用Android Extensions Gradle插件:

apply plugin: 'kotlin-android-extensions'

2、导入合成属性

可以通过如下方式一次性导入某个布局下所有资源作为合成属性:

import kotlinx.android.synthetic.main..*

例如:如果布局文件名为activity_main.xml,我们将导入kotlinx.android.synthetic.main.activity_main.*,如果你需要在View上调用合成属性(在Adapter中比较有用),我们还应该导入kotlinx.android.synthetic.main.activity_main.view.*。这样之后我们即可直接使用合成属性(为了代码规范,建议在xml中id命名使用驼峰写法),例如:

<TextView
	android:id="@+id/textView"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:text="Hello World, MyActivity"
/>

Activity中就会有一个名为textView的属性,代码可以这样写:

this.textView.setText("Hi!")

但如果xml内定义id为text_view,代码就只能替换为:

this.text_view.setText("Hi!")

Android Flavors
Kotlin Android Extensions同样支持Android的差异化打包。假设你的build.gradle文件中有一个名为free的productFlavors配置:

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

你可以通过如下方式导入free/res/layout/activity_free.xml布局的所有合成属性:

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

底层实现
Kotlin Android Extensions是Kotlin编译器的插件,它主要做了两件事:

1、在每个Kotlin Activity中添加一个隐藏的缓存功能和一个字段。方法很小,所以它不会增加APK的大小。
2、用函数调用替换每个合成属性调用。

原理是依托Kotlin动态扩展类(实际并未扩展,只是编译器以及IDE做了一些伪装)的特性给Activity增加合成属性,当调用合成属性时,如果接收方是Kotlin Activity或Fragment类,缓存函数将被调用。例如给定

class MyActivity : Activity()
fun MyActivity.a() { 
    this.textView.setText("")
}

在MyActivity内部会生成隐藏的缓存功能,所以在可能的情况,底层会使用缓存机制以提高效率。

但在以下情况下:

fun Activity.b() { 
    this.textView.setText("")
}

无法知道这个函数是Kotlin Activity还是Java Activity。因此,即使接收器是上一个示例中的MyActivity,也不会缓存。

框架支持

和其他语言类似,Android开发界也有许多为简化开发而生的流行框架,在切到Kotlin开发的同时,依然可以使用相同的框架,但因为这些框架都是基于Java的,所以使用上还是有些小差异,常用的诸如Dagger,Butterknife(上面提到的Kotlin Android Extensions配合Anko已经可以覆盖此框架功能,如果不介意可以考虑替换),Data Binding,Auto-parcel和DBFlow等都可以通过注释处理。在Kotlin中,你可以使用Kotlin注释处理工具(kapt)以类似于Java annotationProcessor的方式指定依赖关系。

需要使用时可以导入

apply plugin: 'kotlin-kapt'

其他注解方式基本无异,个别情况下,只需根据Kotlin语言特性对注解的位置及代码的形式做些许调整,关于这些框架的支持可以参考官网,链接见文章末尾。

参考:
http://kotlinlang.org/docs/tutorials/android-plugin.html
http://kotlinlang.org/docs/tutorials/android-frameworks.html