美文网首页
DataBinding原理深入理解

DataBinding原理深入理解

作者: 浪里_个郎 | 来源:发表于2020-05-19 10:06 被阅读0次

DataBinding的三种写法

我们使用DataBinding可以实现绑定字段和View的绑定,注意有单向绑定和双向绑定之分。对于系统控件,双向绑定的区别是要通过@={},即多一个=号来设置数据源。
进行数据绑定有三种写法:

1,直接在layout中使用基本类型:

<data>
  <variable
    name="isLoading"
    type="boolean" />
</data>

2,绑定类成员变量,类继承BaseObservable或实现Observable接口,但是需要自行处理一些接口方法逻辑。同时,需要用@Bindable标记实体类中的get方法或“is”开头的方法:


public class User extends BaseObservable {
 
    private String name;
    private int age;
    private String sex;
    private boolean isStudent;
 
    @Bindable
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(com.qiangxi.databindingdemo.BR.name);
    }
 
    @Bindable
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
        notifyPropertyChanged(com.qiangxi.databindingdemo.BR.age);
    }
 
    @Bindable
    public String getSex() {
        return sex;
    }
 
    public void setSex(String sex) {
        this.sex = sex;
        notifyPropertyChanged(com.qiangxi.databindingdemo.BR.sex);
    }
 
    @Bindable
    public boolean isStudent() {
        return isStudent;
    }
 
    public void setStudent(boolean student) {
        isStudent = student;
        notifyPropertyChanged(com.qiangxi.databindingdemo.BR.student);
    }
 
    @Bindable({"name", "age", "sex", "isStudent"})
    public String getAll() {
        return "姓名:" + name + ",年龄=" + age + ",性别:" + sex + ",是不是学生=" + isStudent;
    }
}

3,绑定的成员变量使用Observable包装类:

针对8种基本类型的数据结构提供了专门的包装类
ObservableBoolean
ObservableByte
ObservableChar
ObservableDouble
ObservableFloat
ObservableInt
ObservableLong
ObservableShort
针对集合提供的包装类
ObservableArrayList
ObservableArrayMap
针对实现了Parcelable接口的对象提供的包装类
ObservableParcelable
针对其他类型提供的包装类
ObservableField。最典型的:ObservableField

public class User02 {
    public final ObservableField<String> name = new ObservableField<>();
    public final ObservableInt age = new ObservableInt();
    public final ObservableField<String> sex = new ObservableField<>();
    public final ObservableBoolean isStudent = new ObservableBoolean();
}

那么,DataBinding框架到底做了什么?

DataBinding原理

我们定义一个绑定数据:

public class LoginViewModel extends ViewModel {

    public final ObservableField<String> name = new ObservableField<>();

    public final ObservableField<String> password = new ObservableField<>();

    public final ObservableBoolean loadingVisible = new ObservableBoolean();

}
    <data>
        <variable
            name="vm"
            type="com.kunminx.puremusic.bridge.state.LoginViewModel" />
    </data>

首先来看DataBinding为我们自动生成的XXXImpl类有什么:

    //自动生成了set方法,
    @Override
    public boolean setVariable(int variableId, @Nullable Object variable)  {
        boolean variableSet = true;
        if (BR.vm == variableId) {
            setVm((com.kunminx.puremusic.bridge.state.LoginViewModel) variable);
        }
        else if (BR.click == variableId) {
            setClick((com.kunminx.puremusic.ui.page.LoginFragment.ClickProxy) variable);
        }
        else {
            variableSet = false;
        }
            return variableSet;
    }

    public void setVm(@Nullable com.kunminx.puremusic.bridge.state.LoginViewModel Vm) {
        this.mVm = Vm;
        synchronized(this) {
            mDirtyFlags |= 0x8L;
        }
        //不做特殊处理,该方法没有作用
        notifyPropertyChanged(BR.vm);
        super.requestRebind();
    }

我们就可以通过调用XXXbinding的setVariable获setVm方法,将绑定数据实例(这里就是ViewModel)传入了。

然后下面这个方法中,实现了数据影响UI显示:

    //绑定的数据一旦变化,就会调进这个方法
    //我们也可以调用自动生成的XXXBinding.executePendingBindings(),主动调入该函数来刷新UI
    @Override
    protected void executeBindings() {
    ...
        //这里就是通过观察者模式,监视绑定的数据。数据一旦变化,就会
        updateRegistration(0, vmPassword);
        ...
        updateRegistration(2, vmName);
    ...

        //下面是根据数据修改UI
        if ((dirtyFlags & 0x20L) != 0) {
            // api target 1

            this.btnBack.setOnClickListener(mCallback8);
            this.btnLogin.setOnClickListener(mCallback9);
            com.kunminx.architecture.ui.binding.Drawables.setViewBackground(this.btnLogin, (int)0, 0xffFF7055, (int)0, (float)0f, (float)0f, (float)0f, 25, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null);
            com.kunminx.architecture.ui.binding.Drawables.setViewBackground(this.etName, (int)0, (java.lang.Integer)null, 0xffeeeeee, 1, (float)0f, (float)0f, 12, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null);
            androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.etName, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, etNameandroidTextAttrChanged);
            com.kunminx.architecture.ui.binding.Drawables.setViewBackground(this.etPwd, (int)0, (java.lang.Integer)null, 0xffeeeeee, 1, (float)0f, (float)0f, 12, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (int)0, (java.lang.Integer)null, (int)0, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (java.lang.Integer)null, (java.lang.Integer)null, (java.lang.Integer)null, (int)0, (int)0, (java.lang.Float)null, (java.lang.Float)null, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (float)0f, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null, (android.graphics.drawable.Drawable)null);
            androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.etPwd, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, etPwdandroidTextAttrChanged);
        }
        if ((dirtyFlags & 0x2cL) != 0) {
            // api target 1

            androidx.databinding.adapters.TextViewBindingAdapter.setText(this.etName, vmNameGet);
        }
        if ((dirtyFlags & 0x29L) != 0) {
            // api target 1

            androidx.databinding.adapters.TextViewBindingAdapter.setText(this.etPwd, vmPasswordGet);
        }
        if ((dirtyFlags & 0x2aL) != 0) {
            // api target 1

            com.kunminx.puremusic.ui.base.binding.CommonBindingAdapter.visible(this.progress, vmLoadingVisibleGet);
        }

看到这里,我们终于明白为什么绑定的数据类型需要是Observable了,因为需要通过updateRegistration注册观察者,来监听绑定的数据,实现数据变化后自动改变UI显示;我们也看到了到底是哪里帮我们自动修改了UI显示,最终还是通过View的方法修改UI。
至于UI变化影响绑定的数据,是在上面代码的setTextWatcher方法调用中实现的。

相关文章

网友评论

      本文标题:DataBinding原理深入理解

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