Kotlin 中的 DataBinding
前言
- 前面一章和大家简单的讲解了 Kotlin 中的变量、方法以及对象声明的定义,今天呢,就和大家讲讲 Kotlin 中的 DataBinding 的使用。
- KotlinTest Github:
添加 DataBinding 依赖
-
在我之前的文章里就有说过如何在项目中使用 DataBinding,当然了,那是在 Java 语言开发中,要是使用 Kotlin 开发的话,还是有所区别的。不了解的可以看看我之前的 Android项目基本架构(四) DataBinding
-
如果使用 Java 开发,那么很简单,只需要在 Module 的 gradle 文件中 android 节点下加入相应设置就可以了:
android { ... dataBinding { enabled true } ... }
-
但是使用 Kotlin 开发这样是远远不够的,除此之外,你还需要手动添加上注解处理依赖,而使用注解处理,你又要添加 kapt 插件支持:
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' // 添加 kapt 插件支持 android { ... dataBinding { // 开启 DataBinding enabled true } ... } kapt { // kapt 配置 generateStubs = true } dependencies{ ... kapt 'com.android.databinding:compiler:2.3.3 // DataBinding 注解处理依赖 ... }
-
Kotlin 中 DataBinding 配置就完成了。
Observable
-
你以为配置好依赖就可正常使用了吗?那你就太天真了,Kotlin 和 Java 还是有很大不同的。
-
还记得 Java 中的用法吗?
public class Entity extends BaseObservable { private boolean show; @Bindable public boolean isShow() { return show; } public void setShow(boolean show){ this.show = show; notifyPropertyChanged(BR.show); } }
-
没错就是这样,@Bindable 注解将变量 show 和 xml 中的布局绑定起来,通过 setShow() 方法变化 show 的值时,xml 中与之对应的布局也会随之变化。
-
但是在 Kotlin 中你是不用像 Java 中一样手动去生成 getter 和 setter 的, Kotlin 中你只需要声明一个属性,那么就会自动生成默认的 getter 、setter。
class Entity : BaseObservable() { var show: Boolean = false }
-
在使用 Kotlin 的时候你会发现很多代码像这样:list.adapter = ListAdapter(),这其实是调用了默认的 setter。
-
这个时候,该怎么使用 Observable 呢?之前查找资料的时候看到很多文章多说没有办法像 Java 中一样使用,需要使用 ObservablerBoolean、ObservableString 等封装类,但是实际上是不用这样的,因为虽然 Kotlin 有默认的 getter、setter,但是同样你也可以自己进行定义。
-
如果你不知道如何定义,可以使用 Kotlin 提供的工具 Convert Java File to Kotlin File 将 Java 代码转换为 Kotlin 代码,于是就成了这样:
class Entity : BaseObservable { @set:Bindable var id: Int = 0 set(id) { field = id notifyPropertyChanged(BR.id) } }
-
所有的 Observable 都可以以这种形式定义。
Component
-
但是,你要知道, Kotlin 提供的 Convert Java File to Kotlin File 工具并不是完美的,很多地方并不是直接这么转换就可以了。
-
在 Java 中使用 DataBindingAdapter 是这样的
public class DatBindingAdapter { @BindingAdapter("img_url") public static void imgUrl(ImageView iv, String imgUrl) { Glide.with(iv.getContext()) .load(imgUrl) .into(iv); } }
-
如果你在这里使用工具进行转换,你会发现他会转换成对象声明:
object DataBindingAdapter { @BindingAdapter("img_url") fun imgUrl(iv: ImagerView, imgUrl: String) { Glide.with(iv.getContext()) .load(imgUrl) .into(iv); } }
-
这样的话在使用的时候就会报错,因为方法不是静态的,这个时候就有两种解决方式。
-
如果你不想变动 DataBindingAdapter 的内容,那么你就要在使用 DataBinding 前对 Component 进行设置,比如在 Application 类中:
class MyApplication : Application() { override fun onCreate() { super.onCreate() DataBindingUtil.setDefaultComponent(object : DataBindingComponent { // 手动设置 Component ovverride fun getDataBindingAdapter() : DataBindingAdapter { return DataBindingAdapter } }) } }
-
这样设置后就可以正常使用了,这里的 object : DataBindingComponent{} 可能有些难以理解,实际上就等同于 Java 中的匿名内部类:
DataBindingUtil.setDefaultComponent(new DataBindingComponent{ @Override public DataBindingAdapter getDataBindingAdapter() { return new DataBindingAdapter(); } });
-
如果你觉得这样设置麻烦,你也可以选择另一种做法:
class DataBindingAdapter{ companion object { @BindingAdapter("img_url") @JvmStatic fun imgUrl(iv: ImagerView, imgUrl: String) { Glide.with(iv.getContext()) .load(imgUrl) .into(iv); } } }
-
使用 BindingAdapter 要不就手动设置 Component,要不就将方法定义为静态的。
-
但是,Java 的 static 关键字并不是 Kotlin 语言的一部分,作为替代,Kotlin 提供了包级别函数(我们之后在详细说明)和对象声明。
-
在我的上一篇文章中说到了对象声明,使用关键字 object,一定义即存在。上面的代码中涉及到了 Kotlin 中的伴生对象,使用 companion 关键字修饰,伴生对象中的属性、方法可以直接通过类名.调用,即 DataBindingAdapter.imgUrl(iv, imgUrl) ,类似于 Java 中的静态常量、静态方法。但是,这样还是不够,因为这并不是静态方法,只是类似,这时就要使用注解 @JvmStatic 来标记这个方法就是静态方法。这样 DataBindingAdapter 就可以正常使用了。
最后
- 关于 DataBinding 在 Kotlin 中的使用就是这样,如果使用中有什么问题可以在评论区提问。
- 接下来还会继续加入 Dagger2 、基类封装等,欢迎关注~
- 最后的最后,Android Studio 3.0 发布正式版啦~