DataBinding实现MVVM

这里写图片描述
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&lt;String, Object&gt;"/>
</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;
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值