Kotlin 中的 DataBinding

作者: WangJie0822 | 来源:发表于2017-10-26 14:10 被阅读89次
    image.png

    前言


    • 前面一章和大家简单的讲解了 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 发布正式版啦~

    相关文章

      网友评论

      本文标题:Kotlin 中的 DataBinding

      本文链接:https://www.haomeiwen.com/subject/xjwhpxtx.html