搞定DataBinding-03

Java中实现的观察者模式核心角色

Observable(被观察者):

当数据发生改变时,向它的各个Observer(观察者)发出通知;

public class Observable {
    public synchronized void addObserver(Observer o) {
        ...
    }

    public synchronized void deleteObserver(Observer o) {
        ...
    }
    /**
     * 通知Observer数据变化
     */
    public void notifyObservers() {
        notifyObservers(null);
    }
}
Observer(观察者):

向Observable(可观察者)注册,当接收通知时更新

public interface Observer {

    /**
     * Observable变化时调用
     */
    void update(Observable observable, Object data);
}

DataBinding观察者

DataBinding观察者模式实现有些区别,对数据只实现了”pull”的方式。
Observer(观察者):
ViewDataBinding自动完成向Observable(被观察者)注册和更新
Observable(被观察者):
Observable可以继承BaseObservable、实现Observable接口、使用ObservableField
Android实现的BaseObservable

public class BaseObservable implements Observable {
    private transient PropertyChangeRegistry mCallbacks;//注册Observers

    public BaseObservable() {
    }
}

不想继承BaseObservable,可以直接使用ObservableField:

ObservableField<T>
ObservableParcelable<T extends Parcelable>
ObservableArrayList
ObservableArrayMap
ObservableBoolean
...

DataBinding调用链路

  1. Observable的定义
  2. ViewDataBinding创建
  3. executeBindings(),会注册好回调(Observer)
  4. Observable数据更新
  5. ViewDataBinding.requestRebind()
定义Observable
public class VehicleInfo extends BaseModel {
    private ObservableBoolean isSelected;
    private String  logoUrl;
    private String  brand;
    private String  description;
}
创建ViewDataBinding
@Override
public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
    final VehicleInfo info = getItem(position);
    if(holder instanceof ViewHolder){
        ViewDataBinding binding = ((ViewHolder) holder).getBinding();
        binding.setVariable(BR.info, info);
        binding.setVariable(BR.itemCLick, itemListener);
        binding.setVariable(BR.selectedCLick, selectedListener);
        binding.executePendingBindings();
    }
}
注册观察者

在executePendingBindings()中完成,CreateWeakListener充当Observer

private boolean updateRegistration(int localFieldId, Object observable,
        CreateWeakListener listenerCreator) {
    if (observable == null) {
        return unregisterFrom(localFieldId);
    }
    WeakListener listener = mLocalFieldObservers[localFieldId];
    if (listener == null) {
        registerTo(localFieldId, observable, listenerCreator);
        return true;
    }
    if (listener.getTarget() == observable) {
        return false;//nothing to do, same object
    }
    unregisterFrom(localFieldId);
    registerTo(localFieldId, observable, listenerCreator);
    return true;
}

Observable通知

Observable.OnPropertyChangedCallback()回调更新

   VehicleInfo data = binding.getInfo();
   data.getIsSelected().set(true);

public void set(boolean value) {
    if (value != mValue) {
        mValue = value;
        notifyChange();
    }
}

//mCallbacks.get(i) --> WeakPropertyListener extends OnPropertyChangedCallback
mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg, arg2);

public void onNotifyCallback(Observable.OnPropertyChangedCallback 
            callback, Observable sender,int arg, Void notUsed) {
    callback.onPropertyChanged(sender, arg);
}

//WeakPropertyListener notify之后 回调的方法
private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback{
    @Override
    public void onPropertyChanged(Observable sender, int propertyId) {
        ViewDataBinding binder = mListener.getBinder();
        if (binder == null) {
            return;
        }
        Observable obj = mListener.getTarget();
        if (obj != sender) {
            return; // notification from the wrong object?
        }
        binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
    }
}
ViewDataBinding更新View

handleFieldChange(),如果数据发生变化,调用requestRebind()
不过只会更新需要更新的View,在executeBindings()方法中,这个逻辑比较复杂也不易阅读。
mDirtyFlags标示每一个binding,通过BitMask判断是否需要更新。

    private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
        boolean result = onFieldChange(mLocalFieldId, object, fieldId);
        if (result) {
            requestRebind();
        }
    }

@Override
protected void executeBindings() {
    long dirtyFlags = 0;
    synchronized(this) {
        dirtyFlags = mDirtyFlags;
        mDirtyFlags = 0;
    }
    ...
    //只有isSelectedInfoAndroi改变了, 才更新
    if ((dirtyFlags &amp;amp; 0x13L) != 0) {
        ...
    }
}

GitHub地址

AndroidDataBindingTutorial

Reference

  1. data-binding-part-observer-pattern
  2. Android Data Binding从抵触到爱不释手
  3. 观察者模式
  4. BitMask 使用参考

发表评论

电子邮件地址不会被公开。 必填项已用*标注