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方法调用中实现的。