美文网首页Android-Jetpack
Jetpack系列组件--dataBinding从相遇到相知

Jetpack系列组件--dataBinding从相遇到相知

作者: 蓅哖伊人为谁笑 | 来源:发表于2020-02-14 19:31 被阅读0次
    一、什么是dataBinding
    • 一句话概括dataBinding可以理解为dataBinding只是一种工具,它解决的是View和数据之间的双向绑定。MVVM是一种架构模式,两者是有本质区别的。
    二、 dataBinding的优势
    • 双向数据绑定
      数据发生改变后,自动通知UI刷新页面,不再需要人工绑定最新数据到View上。UI改变后也能同步给数据

    • 减少模板代码
      有了dataBinding,从此不用再写findViewById,setOnClickListener等枯燥生硬的代码,大大提高工作效率。从此Butterknife靠边站。

    • 释放Activity/Fragment
      以前,我们在Activity,FragmentPresenter中计算数据再绑定到View组件上,导致View层很臃肿,现在,这部分工作,我们可以直接在xml布局文件中完成。Activity,Fragment让它更加只关注核心业务。

    • 数据绑定空安全
      在xml中绑定数据它是空安全的,因为dataBinding在数据绑定上会自动装箱和空判断,所以大大减少了数据绑定带来的NullpointException问题。

    三、如何引入ViewModel

    需要在使用dataBinding的模块的build.gradle文件中添加dataBinding配置,
    如下所示,

    每个使用dataBinding的模块都应该在build.gradle中添加如下配置

     android {
      ...
      dataBinding {
          enabled = true
      }
    }
    
    
    四、dataBinding如何使用
    • 在布局文件中,选中根布局的标签,按住 Alt + 回车键,点击Convert to data binding layout,即可转换成dataBinding布局。

    • 转换后的布局,最外层变成了layout标签,里面包裹了data标签和常规的布局元素。data元素用来声明在此布局用使用到的变量和变量的类型,以及类引用。

    • 是不是所有属性都能用dataBinding来绑定呢?当然不是! 如果一个属性xxx,在该类中有setXxx方法,我们才能使用dataBinding来绑定。比如android:layout_width,android_layout_height就不能使用dataBinding来绑定值,而android:paddingLeft,android:textSize都是可以的。

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        <data>
            <variable
                name="user"
                type="com.mooc.ppjoke.model.User" />
            <import type="com.mooc.ppjoke.user.UserManager"></import>
        </data>
        <androidx.constraintlayout.widget.ConstraintLayout>
            <TextView
                android:id="@+id/tvName"
                android:layout_width="200dp"  //不能使用dataBinding动态绑定
                android:text="@{user.name}"  //单向绑定数据变更自动通知UI
                android:textSize="@{@dimen/16sp}"//资源引用
                android:text="@{user.name+@string/suffix}"  //字符串的拼接需要引用资源 
                android:text="@{UserManager.getUserName()}" //调用静态方法,类必须先导入
                android:onClick="@{()-> UserManager.login()}"
              />
    
          <EditText
                //双向绑定数据变更自动更新UI,UI变更了也能自动更新user中name的数据,比单向绑定多个=
                android:text="@={user.name}" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    

    android:text="@{user.name}"等价于tvName.text = user.name这样就将数据和View相关联了。
    那么如何实现View和数据的双向绑定呢?我们只需要让实体类User继承BaseObservable。当user中字段发生变更,只需要调用user.notifyPropertyChanged就可以让UI刷新。

    public class User extends BaseObservable  {
        public String name;
        //当使用name字段发生变更后,若想UI自动刷新,我们需要给它写个get方法并且标记Bindable注解。
        //最后调用notifyPropertyChanged方法即可
        @Bindable                   
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
            notifyPropertyChanged(com.mooc.ppjoke.BR.user);
        }
    }
    

    dataBinding 也支持在布局文件中使用 数组、LsitSetMap,且在布局文件中都可以通过 list[index] 的形式来获取元素,因为xml的特性,在声明 Lsit< String > 之类的数据类型时,需要使用尖括号的转义字符(在下面)

    <?xml version="1.0" encoding="utf-8"?>
    <layout >
        <data>
            <import type="java.util.List" /> <import type="java.util.Map" />
            <import type="java.util.Set" /> <import type="android.util.SparseArray" />
            <variable
                name="array"
                type="String[]" />
            <variable
                name="list"
                type="List&lt;String&gt;" />            //List<String> 其中<和>俩字符需要转义
            <variable
                name="map"
                type="Map&lt;String, String&gt;" />     //Map<String>
            <variable
                name="set"
                type="Set&lt;String&gt;" />                //Set<String>
            <variable
                name="sparse"
                type="SparseArray&lt;String&gt;" />  //SparseArray<String>
            <variable
                name="index"
                type="int" />
            <variable
                name="key"
                type="String" />
        </data>
    
        <LinearLayout>
            <TextView
                android:text="@{array[1]}" />
    
            <TextView
                android:text="@{sparse[index]}" />
    
            <TextView
                android:text="@{list[index]}" />
    
            <TextView
                android:text="@{map[key]}" />
    
            <TextView
                android:text='@{map["慕课jetpack"]}' />
    
            <TextView
                android:text='@{set.contains("xxx")?"慕课jetpack":key}' />
        </LinearLayout>
    </layout>
    

    dataBinding在xml中数据绑定支持的语法表达式也是非常丰富的,支持在布局文件中使用以下运算符、表达式和关键字:

    算术运算符 + - / * %
    字符串连接运算符 +
    逻辑运算符 && ||
    二元运算符 & | ^
    一元运算符 + - ! ~
    移位运算符 >> >>> <<
    比较运算符 == > < >= <= (<需要被转义成&lt;>需要被转义为&gt;)
    instanceof
    分组运算符 ()
    字面量运算符 - 字符、字符串、数字、null
    类型转换,方法调用
    字段访问
    数组访问 []
    三元运算符 ?

    不支持以下操作 this,super,new,显示泛型调用

    五、dataBinding如何拓展View属性
    • 我们知道,以前想要给ImageView增加几个属性,必须要写个自定义的ImageView在构造函数中一顿解析。那看看使用dataBinding如何拓展View属性。
       public class PPImageView extends ImageView{
    
       //需要使用BindingAdapter注解并标记在public static方法上。
        //value中的字段随意添加和方法参数一一对应即可。
       @BindingAdapter(value = {"image_url", "isCircle"})
        public static void setImageUrl(PPImageView view, String imageUrl, boolean isCircle) {
            view.setImageUrl(view, imageUrl, isCircle, 0);
        }
        //requireAll = false代表是否以下三个属性在xml中同时使用才会调用到该方法
        //为false的话,只要有一个属性被使用就能调用到该方法
        @BindingAdapter(value = {"image_url", "isCircle", "radius"}, requireAll = false)
        public static void setImageUrl(PPImageView view, String imageUrl, boolean isCircle, int radius) {
           ......
          }
       }
    
    //在布局文件中如下使用,便能实现图片圆角和资源Url绑定的功能
     <com.mooc.ppjoke.view.PPImageView
                .......
                app:image_url ="@{user.avatar}"
                app:radius="@{50}">
    </com.mooc.ppjoke.view.PPImageView>
    
    六、dataBinding使用的建议
    • fragment_layout_my.xml布局,在编译时会生成FragmentLayoutMyImpl.java,我们可以搜索这种类debug跟进解决问题。

    • 不建议在列表中乱用,因为dataBinding数据绑定是延迟一帧的,如果列表中的ItemView的宽高需要计算后才能正确展示,不建议使用dataBinding操作,否则会看到列表ItemView明显的撑开动画,体验不好。

    • 实体类配合BaseObservable可以友好的解决数据双向绑定的问题

    一起拥抱Jetpack
    1.Jetpack全系列组件高级用法&原理分析实战
    2.Jetpack系列组件--LiveData从相遇到相知
    3.Jetpack系列组件--ViewModel从相遇到相知
    4.Jetpack系列组件--优雅的打造一款事件总线LiveDataBus
    5.Jetpack系列组件--列表分页库Paging从相遇到相知
    6.Jetpack系列组件--Navigation组件工作原理分析&灵活改造应用
    7.Jetpack系列组件--dataBinding从相遇到相知

    相关文章

      网友评论

        本文标题:Jetpack系列组件--dataBinding从相遇到相知

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