接上篇,整理一下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