ViewModel和Model双向绑定,ViewModel和View单向绑定
Observable
任何 POJO 对象都能用在 Data Binding 中,但是更改 POJO 并不会同步更新 UI。Data Binding 的强大之处就在于它可以让你的数据拥有更新通知的能力。
有三种不同的动态更新数据的机制:
Observable 对象
Observable 字段
Observable 容器类
当以上的 observable 对象绑定在 UI 上,数据发生变化时,UI 就会同步更新。
Observable 对象
当一个类实现了 Observable 接口时,Data Binding 会设置一个 listener 在绑定的对象上,以便监听对象字段的变动。
Observable 接口有一个添加/移除 listener 的机制,但通知取决于开发者。为了简化开发,Android 原生提供了一个基类 BaseObservable 来实现 listener 注册机制。这个类也实现了字段变动的通知,只需要在 getter 上使用 Bindable 注解,并在 setter 中通知更新即可。
public class ObservableContact extends BaseObservable {
private String mName;
private String mPhone;
public ObservableContact(String name, String phone) {
mName = name;
mPhone = phone;
}
@Bindable
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
notifyPropertyChanged(BR.name);
}
@Bindable
public String getPhone() {
return mPhone;
}
public void setPhone(String phone) {
mPhone = phone;
notifyPropertyChanged(BR.phone);
}
}
BR 是编译阶段生成的一个类,功能与 R.java 类似,用 @Bindable 标记过 getter 方法会在 BR 中生成一个 entry。
当数据发生变化时需要调用 notifyPropertyChanged(BR.firstName) 通知系统 BR.firstName 这个 entry 的数据已经发生变化以更新UI。
Observable和一般JavaBean在setData()时的区别
多了updateRegistration()
//User是Observable
public void setUser(com.example.fs.databinding.model.User user) {
updateRegistration(0, user);
this.mUser = user;
synchronized(this) {
mDirtyFlags |= 0x1L;
}
notifyPropertyChanged(BR.user);
super.requestRebind();
}
public void setHandler(ClickHandler handler) {
this.mHandler = handler;
synchronized(this) {
mDirtyFlags |= 0x2L;
}
notifyPropertyChanged(BR.handler);
super.requestRebind();
}
updateRegistration()创建弱引用了DataBinding的Listener,以lacalFieldId作为key存储起来。绑定Listener到Observable,也就是绑定DataBinding到Obervable。由于Listener注册并实现一个Callback,当Observable数据发生变化notifyPropertyChanged()时,可以通知Callback实现对View的更新,最终调用onFieldChange(int localFieldId, Object object, int fieldId)。
fieldId:用 @Bindable 标记过 getter 方法的数据,在BR中会生成一个entry,
ObservableField
创建ObservableField类型public数据对象,ObservableFields 是继承自Observable 对象的单一字段。
public class ObservableFieldContact {
public ObservableField<String> mName = new ObservableField<>();
public ObservableFieldContact(String name) {
mName.set(name);
}
}
使用数据时
mObservableFieldContact.mName.set("ConnorLin");
String name = mObservableFieldContact.mName.get();
和继承Observable的区别是在executeBindings()里注册ObservableField的监听
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
...
if ((dirtyFlags & 0xfL) != 0) {
if ((dirtyFlags & 0xdL) != 0) {
if (contact != null) {
// read contact.mName
mNameContact = contact.mName;
}
updateRegistration(0, mNameContact);
...
}
...
}
Observable 容器类
ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("firstName", "Google");
user.put("lastName", "Inc.");
user.put("age", 17);
layout中使用
<data>
<import type="android.databinding.ObservableMap"/>
<variable name="user" type="ObservableMap<String, Object>"/>
</data>
…
<TextView
android:text='@{user["lastName"]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text='@{String.valueOf(1 + (Integer)user["age"])}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
事件绑定(View->Model)
Binding构造方法中会为View创建监听,每个监听有对应的控件序号
public ActivityObservableBinding(android.databinding.DataBindingComponent bindingComponent, View root) {
super(bindingComponent, root, 2);
...
// listeners,2、1和下面的sourceId对应
mCallback2 = new android.databinding.generated.callback.OnClickListener(this, 2);
mCallback1 = new android.databinding.generated.callback.OnClickListener(this, 1);
invalidateAll();
}
executeBindings时设置监听,当事件回调时,根据控件序号执行Handler对应的onClick()方法
public final void _internalCallbackOnClick(int sourceId , android.view.View callbackArg_0) {
switch(sourceId) {
case 2: {
...
handler.onClick(callbackArg_0);
...
break;
}
case 1: {
// localize variables for thread safety
...
handler.onClick();
...
break;
}
}
}