79.DataBinding使用及原理解析

2020-08-14  本文已影响0人  SlideException

https://www.jianshu.com/p/de4d50b88437
build.gradle 里添加

android{
 dataBinding {
        enabled = true
    }
}

新建实体类UserBean实现BaseObservable:

public class UserBean extends BaseObservable{
   private String name;
    private String gender;
    public final ObservableField<Integer> age = new ObservableField<>();
    public UserBean(String name, String gender,int age) {
        this.name = name;
        this.gender = gender;
        this.age.set(age);
    }
    @Bindable
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }
    @Bindable
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
        notifyPropertyChanged(BR.gender);
    }
}

activity_databinding.xml中:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="userBean"
            type="com.example.UserBean" />
    </data>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:text="@{userBean.name}"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:text="@{userBean.gender}"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:text="@{String.valueOf(userBean.age)}"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/uid_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>
</layout>

activity中:

 ActivityDatabindingBinding databindingBinding = DataBindingUtil.setContentView(this, R.layout.activity_databinding);

        UserBean userBean = new UserBean("张三","男",16);
        databindingBinding.setUserBean(userBean);

        databindingBinding.uidBtn.setOnClickListener((v)->{
            userBean.setGender("女");
            userBean.setName("李思");
            userBean.age.set(18);
        });

这里的ActivityDatabindingBinding是根据xml布局文件的名字自动生成的,比如xml叫xml_test.xml就会生成XmlTestBinding。

DataBinding主要解决了两个问题:

  1. 需要多次findViewById。
  2. 更新数据时需要切换至UI线程。当你的Activity需要展示新的数据时,你可以在后台线程中获取数据,然后直接交给DataBinding就可以了,完全不需要关心线程切换的问题。
    DataBinding解决这些问题,就是针对每个activity布局,在编译阶段,生成一个viewDataBinding类的对象,该对象持有activity要展示的数据和布局中的各个view的引用,数据和展示的布局紧紧绑定在一起。

DataBinding背后做了什么

1.DataBinding会对根元素为<layout>的布局文件进行预处理,会对根元素和那些在属性中使用了binding表达式的view设置成Tag,而原有的<layout>标签<data><variable>和各个view中的binding表达式都不见了。DataBinding会把这些内容抽取出来生成一个activity_databinding-layout.xml文件。
2.生成ActivityDatabindingBinding类、ActivityDatabindingBindingImpl类与BR类,ActivityDatabindingBindingImpl中会生成对应xml文件里的view

  // views
    @NonNull private final android.widget.LinearLayout mboundView0;
    @NonNull private final android.widget.TextView mboundView1;
    @NonNull private final android.widget.TextView mboundView2;
    @NonNull private final android.widget.TextView mboundView3;

生成的BR类

public class BR {
  public static final int _all = 0;
  public static final int gender = 1;
  public static final int name = 2;
  public static final int userBean = 3;
}

在实体类(继承了BaseObservable的)的属性的get方法中添加了@Bindable注解的才会在BR类中生成对应的变量,_all是自动生成的。
实际上,BR中的常量是一种标识符,它对应一个会发生变化的数据,当数据改变后,你可以用该标识符通知DataBinding,很快,DataBinding就会用新的数据去更新UI。

3.生成ActivityDatabindingBinding实例并绑定,
这里主要分三个步骤
①inflate处理后的布局文件得到一个viewgroup变量root,
②DataBindingUtil会将这个变量root传递给ActivityDatabindingBinding的构造方法,生成一个ActivityDatabindingBinding的实例,就是我们在onCreate方法中获取的binding对象,在构造方法中,ActivityDatabindingBinding会首先遍历root,根据各个View的Tag或者id,初始化自己的fields。至此,Tag们的历史使命完成了,ActivityDatabindingBinding将会把之前加到各个View上的Tags清空。
③构造方法调用invalidateAll引发数据绑定,ActivityDatabindingBinding将会计算各个view上的binding表达式,然后赋值给view相应的属性。
赋值的过程实际上就是binding表达式求值的过程,生成的binding类里的临时变量对应的并不是实体类中的成员变量,而是实体类中的成员变量的get方法。

上一篇 下一篇

猜你喜欢

热点阅读