Android的DataBinding原理

Activity在inflate layout时,通过DataBindingUtil来生成绑定,从代码看,是遍历contentView得到View数组对象,然后通过数据绑定library生成对应的Binding类,含Views、变量、listeners等。生成类位于 build/intermediates/classes/debug/…package…/databinding/xxx.Java 下,具体如何生成这里暂不作深入。

绑定过程

  • 首先,会在父类(ViewDataBinding)中实例化回调或Handler,用于之后的绑定操作;

    private static final boolean USE_CHOREOGRAPHER = SDK_INT >= 16;

    if (USE_CHOREOGRAPHER) { mChoreographer = Choreographer.getInstance(); mFrameCallback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { mRebindRunnable.run(); } }; } else { mFrameCallback = null; mUIThreadHandler = new Handler(Looper.myLooper()); }

  • 接着,通过调用 mapBindings(…) [遍历布局

    ](www.zhihu.com/search?q=%E… Views的数组对象,再依次赋给对应View

    final Object[] bindings = mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds); this.mboundView0 = (Android.widget.LinearLayout) bindings[0]; this.mboundView0.setTag(null);

  • 然后,调用 invalidateAll() -> requestRebind() -> … -> mRebindRunnable.run() – 执行 Runnable

    // 用于动态重新绑定 Views private final Runnable mRebindRunnable = new Runnable() { @Override public void run() { synchronized (this) { mPendingRebind = false; } ..... executePendingBindings(); } };

  • 最后,通过该Runnable会执行到 executePendingBindings() -> … -> executeBindings(),在这里会执行绑定相关操作。

    @Override protected void executeBindings() { long dirtyFlags = 0; synchronized(this) { dirtyFlags = mDirtyFlags; // mDirtyFlags 变量更新的标志 mDirtyFlags = 0; } ..... }

设置变量(数据对象)

普通 Java bean 对象

  • 首先,通过mDirtyFlags[标识变量

    ](www.zhihu.com/search?q=%E…

    synchronized(this) { mDirtyFlags |= 0x1L; }

  • 然后,调用 notifyPropertyChanged(…) 来通知更新(若有回调)

    public void notifyPropertyChanged(int fieldId) { if (mCallbacks != null) { mCallbacks.notifyCallbacks(this, fieldId, null); } }

  • 最后,调用 requestRebind() -> … -> executeBindings() 再次执行绑定操作,将数据更新到Views上

    @Override protected void executeBindings() { long dirtyFlags = 0; synchronized(this) { dirtyFlags = mDirtyFlags; mDirtyFlags = 0; } ..... }

Observable 对象

  • 在设置变量时,会先调用 updateRegistration(..) 注册一个Observable对象的监听

    public void setContact(com.connorlin.databinding.model.ObservableContact contact) { updateRegistration(0, contact); this.mContact = contact; synchronized(this) { mDirtyFlags |= 0x1L; } notifyPropertyChanged(BR.contact); super.requestRebind(); }

  • 其他步骤同普通 Java bean 对象

ObservableFields 对象

  • 前期步骤同普通 Java Bean 对象

  • 与 Observable 对象不同的是,Observable对象的监听是在 executeBindings() 中注册的

    @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);

            if (mNameContact != null) {
                // read contact.mName.get()
                mNameContact1 = mNameContact.get();
            }
        }
        ...
    }
    ...
    复制代码

    }

注册Observable对象监听

  • 入口 updateRegistration(0, contact) :

    protected boolean updateRegistration(int localFieldId, Observable observable) { return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER); }

    private boolean updateRegistration(int localFieldId, Object observable, CreateWeakListener listenerCreator) { ... // 确保不重复监听,先移除再添加观察监听 unregisterFrom(localFieldId); registerTo(localFieldId, observable, listenerCreator); return true; }

    protected void registerTo(int localFieldId, Object observable, CreateWeakListener listenerCreator) { if (observable == null) { return; }

    // 创建对象监听并存到mLocalFieldObservers中
    WeakListener listener = mLocalFieldObservers[localFieldId];
    if (listener == null) {
        // CREATE_PROPERTY_LISTENER -> create(...)
        listener = listenerCreator.create(this, localFieldId);
        mLocalFieldObservers[localFieldId] = listener;
    }
    
    // 将监听绑定到Observable对象上
    listener.setTarget(observable);
    复制代码

    }

每个Observable对象都会添加一个观察监听,保存在数组 mLocalFieldObservers 中,并以 localFieldId 索引。

  • CREATE_PROPERTY_LISTENER 为何物?

    private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() { @Override public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) { // 返回从WeakPropertyListener实例中获取的监听器(WeakListener) return new WeakPropertyListener(viewDataBinding, localFieldId).getListener(); } }

    private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback implements ObservableReference { final WeakListener mListener;

    public WeakPropertyListener(ViewDataBinding binder, int localFieldId) {
        mListener = new WeakListener<Observable>(binder, localFieldId, this);
    }
    
    @Override
    public WeakListener<Observable> getListener() {
        return mListener;
    }
    
    @Override
    public void addListener(Observable target) {
        // WeakPropertyListener 继承于 Observable.OnPropertyChangedCallback,
        // 所以 this 其实就是 Observable对象的属性监听器
        target.addOnPropertyChangedCallback(this);
    }
    
    ...
    复制代码

    }

    private static class WeakListener extends WeakReference { private final ObservableReference mObservable; protected final int mLocalFieldId; private T mTarget;

    ...
    
    public void setTarget(T object) {
        unregister();
        mTarget = object;
        if (mTarget != null) {
            // mObservable 是上面的 WeakPropertyListener对象
            // mTarget 是绑定到listener上得Observable对象
            mObservable.addListener(mTarget);
        }
    }
    
    ...
    复制代码

    }

CREATE_PROPERTY_LISTENER 实际上只是一个接口实例,注册时会调用它的create()方法创建一个弱引用listener,它的作用是将listener绑定到Observable对象上, 绑定时,会调用 listener.setTarget(…) 将Observable对象传给 WeakPropertyListener实例,然后,WeakPropertyListener 会为 Observable对象添加OnPropertyChangedCallback。

  • addOnPropertyChangedCallback实现

addOnPropertyChangedCallback 在 BaseObservable中实现,首先会实例化一个PropertyChangeRegistry对象,同时创建一个用来通知Observable对象重新绑定更新的回调CallbackRegistry.NotifierCallback。然后将 OnPropertyChangedCallback 添加到PropertyChangeRegistry的回调列表中

@Override
public synchronized void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
    if (mCallbacks == null) {
        mCallbacks = new PropertyChangeRegistry();
    }
    mCallbacks.add(callback);
}
复制代码

这样,注册Observable

对象的监听就完毕了。

更新(重新绑定)Observable对象

设置或更新Observable对象时都会调用notifyPropertyChanged()或notifyChange()来通知更新,那到底是如何更新的呢?

  • 回调过程

    public void notifyPropertyChanged(int fieldId) { // mCallbacks 是 PropertyChangeRegistry对象,在 addOnPropertyChangedCallback 时实例化 // 如果注册了Observable对象监听,那么mCallbacks不为null if (mCallbacks != null) { mCallbacks.notifyCallbacks(this, fieldId, null); } }

    // baseLibrary private void notifyCallbacks(T sender, int arg, A arg2, int startIndex, int endIndex, long bits) { long bitMask = 1L; for(int i = startIndex; i < endIndex; ++i) { if((bits & bitMask) == 0L) { // mNotifier 是实例化PropertyChangeRegistry时创建的 // mNotifier 即 CallbackRegistry.NotifierCallback this.mNotifier.onNotifyCallback(this.mCallbacks.get(i), sender, arg, arg2); } bitMask <<= 1; } }

    // PropertyChangeRegistry.NOTIFIER_CALLBACK public void onNotifyCallback(Observable.OnPropertyChangedCallback callback, Observable sender, int arg, Void notUsed) { // callback 是为Observable对象添加的OnPropertyChangedCallback,即WeakPropertyListener callback.onPropertyChanged(sender, arg); }

    // WeakPropertyListener public void onPropertyChanged(Observable sender, int propertyId) { // binder 即生成的Binding类对象 ViewDataBinding binder = mListener.getBinder(); ... binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId); }

    private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) { // onFieldChange 实现在生成的Binding类中 boolean result = onFieldChange(mLocalFieldId, object, fieldId); if (result) { // 如果对象属性变化,将重新绑定 requestRebind(); } }

通过 notifyPropertyChanged 调用到 mNotifier 回调, mNotifier 通知OnPropertyChangedCallback Observable对象属性发生变化,然后在onPropertyChanged中又转给ViewDataBinding对象(生成的Binding类)处理。

  • 判断是否需要重新绑定并执行,在生成的Binding类中实现

    // 生成的Binding类中得方法 protected boolean onFieldChange(int localFieldId, Object object, int fieldId) { // 如果变量不是Observable类型或没有添加 Bindable注解,就不会判断,直接返回false switch (localFieldId) { case 0 : return onChangeContact((com.connorlin.databinding.model.ObservableContact) object, fieldId); } return false; }

    private boolean onChangeContact(com.connorlin.databinding.model.ObservableContact contact, int fieldId) { switch (fieldId) { case BR.name: { synchronized(this) { mDirtyFlags |= 0x4L;// 通过mDirtyFlags判断对象是否变化 } return true; } ... } return false; }

至此,更新过程完毕。

整个注册与更新过程可以用一张流程图来概括:

事件处理

事件处理的原理很简单,在生成Binding类中会实现View事件的监听,在构造时实例化View的事件监听,然后在绑定时将事件监听对象赋值给对应View,这样,点击时就会触发相应的监听。

这里以 DataBindingDemo 中 EventActivity部分为例:

  • 生成的Binding类并实现View的事件监听

    public class ActivityEventBinding extends Android.databinding.ViewDataBinding implements Android.databinding.generated.callback.OnCheckedChangeListener.Listener, Android.databinding.generated.callback.OnClickListener.Listener { // Checkbox check监听 private final Android.widget.CompoundButton.OnCheckedChangeListener mCallback3; private final Android.view.View.OnClickListener mCallback2; private final Android.view.View.OnClickListener mCallback1; // listeners private OnClickListenerImpl mAndroidViewViewOnCl; ... // Listener Stub Implementations public static class OnClickListenerImpl implements Android.view.View.OnClickListener{ private com.connorlin.databinding.handler.EventHandler value; public OnClickListenerImpl setValue(com.connorlin.databinding.handler.EventHandler value) { this.value = value; return value == null ? null : this; } @Override public void onClick(Android.view.View arg0) { this.value.onClickFriend(arg0); } } ... }

  • 实例化View的事件监听

    public ActivityEventBinding(Android.databinding.DataBindingComponent bindingComponent, View root) { super(bindingComponent, root, 0); ... // listeners mCallback3 = new Android.databinding.generated.callback.OnCheckedChangeListener(this, 3); mCallback2 = new Android.databinding.generated.callback.OnClickListener(this, 2); mCallback1 = new Android.databinding.generated.callback.OnClickListener(this, 1); invalidateAll(); }

  • 在执行绑定中绑定View事件监听

    @Override protected void executeBindings() { ... if ((dirtyFlags & 0x6L) != 0) { if (handler != null) { // read handler::onClickFriend AndroidViewViewOnCli = (((mAndroidViewViewOnCl == null) ? (mAndroidViewViewOnCl = new OnClickListenerImpl()) : mAndroidViewViewOnCl).setValue(handler)); } } // batch finished if ((dirtyFlags & 0x6L) != 0) { this.mboundView1.setOnClickListener(AndroidViewViewOnCli); } if ((dirtyFlags & 0x4L) != 0) { this.mboundView2.setOnClickListener(mCallback1); this.mboundView3.setOnClickListener(mCallback2); Android.databinding.adapters.CompoundButtonBindingAdapter.setListeners( this.mboundView4, mCallback3, (Android.databinding.InverseBindingListener)null); } }

  • 触发事件并执行

ViewStub

原理类似,只是利用 ViewStubProxy 来延迟绑定。

  • 使用layout中的ViewStub实例化一个ViewStubProxy对象赋给[viewstub变量

    ](www.zhihu.com/search?q=vi…

    public ActivityViewStubBinding(Android.databinding.DataBindingComponent bindingComponent, View root) { super(bindingComponent, root, 0); final Object[] bindings = mapBindings(bindingComponent, root, 2, sIncludes, sViewsWithIds); ... this.viewStub = new Android.databinding.ViewStubProxy((Android.view.ViewStub) bindings[1]); this.viewStub.setContainingBinding(this); ... }

  • 实例化ViewStubProxy的同时会注册inflate监听

    private OnInflateListener mProxyListener = new OnInflateListener() { @Override public void onInflate(ViewStub stub, View inflated) { mRoot = inflated; mViewDataBinding = DataBindingUtil.bind(mContainingBinding.mBindingComponent, inflated, stub.getLayoutResource()); mViewStub = null;

        if (mOnInflateListener != null) {
            mOnInflateListener.onInflate(stub, inflated);
            mOnInflateListener = null;
        }
        mContainingBinding.invalidateAll();
        mContainingBinding.forceExecuteBindings();
    }
    复制代码

    };

    public ViewStubProxy(ViewStub viewStub) { mViewStub = viewStub; mViewStub.setOnInflateListener(mProxyListener); }

  • inflate ViewStub

    if (!mActivityViewStubBinding.viewStub.isInflated()) { mActivityViewStubBinding.viewStub.getViewStub().inflate(); }

当ViewStub infate时,执行mProxyListener,其中会生成ViewStub的Binding,并强制执行主Binding重绑

  • 绑定ViewStub

    @Override protected void executeBindings() { long dirtyFlags = 0; synchronized(this) { dirtyFlags = mDirtyFlags; mDirtyFlags = 0; } // batch finished if (viewStub.getBinding() != null) { viewStub.getBinding().executePendingBindings(); } }

这样,ViewStub绑定就结束了。

猜你喜欢

转载自juejin.im/post/7039608728710021157