Android的DataBinding原理介绍
Activity在inflate layout時,通過DataBindingUtil來生成綁定,從代碼看,是遍歷contentView得到View數組對象,然后通過數據綁定library生成對應的Binding類,含Views、變量、listeners等。生成類位于
build/intermediates/classes/debug/…package…/databinding/xxx.Java?下,具體如何生成這里暫不作深入。
綁定過程
- 首先,會在父類(ViewDataBinding)中實例化回調或Handler,用于之后的綁定操作;
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(…) 遍歷布局以獲得包含bound、includes、ID Views的數組對象,再依次賦給對應View
this.mboundView0 = (Android.widget.LinearLayout) bindings[0];
this.mboundView0.setTag(null);
- 然后,調用 invalidateAll() -> requestRebind() -> … -> mRebindRunnable.run() – 執(zhí)行 Runnable
private final Runnable mRebindRunnable = new Runnable() {
? ? @Override
? ? public void run() {
? ? ? ? synchronized (this) {
? ? ? ? ? ? mPendingRebind = false;
? ? ? ? }
? ? ? ? .....
? ? ? ? executePendingBindings();
? ? }
};
- 最后,通過該Runnable會執(zhí)行到 executePendingBindings() -> … -> executeBindings(),在這里會執(zhí)行綁定相關操作。
protected void executeBindings() {
? ? long dirtyFlags = 0;
? ? synchronized(this) {
? ? ? ? dirtyFlags = mDirtyFlags; ? // mDirtyFlags 變量更新的標志
? ? ? ? mDirtyFlags = 0;
? ? }
? ? .....
}
設置變量(數據對象)
普通?Java?bean 對象
- 首先,通過mDirtyFlags標識變量(所有變量共用)
? ? mDirtyFlags |= 0x1L;
}
- 然后,調用 notifyPropertyChanged(…) 來通知更新(若有回調)
? ? if (mCallbacks != null) {
? ? ? ? mCallbacks.notifyCallbacks(this, fieldId, null);
? ? }
}
- 最后,調用 requestRebind() -> … -> executeBindings() 再次執(zhí)行綁定操作,將數據更新到Views上
protected void executeBindings() {
? ? long dirtyFlags = 0;
? ? synchronized(this) {
? ? ? ? dirtyFlags = mDirtyFlags;
? ? ? ? mDirtyFlags = 0;
? ? }
? ? .....
}
Observable 對象
- 在設置變量時,會先調用 updateRegistration(..) 注冊一個Observable對象的監(jiān)聽
? ? updateRegistration(0, contact);
? ? this.mContact = contact;
? ? synchronized(this) {
? ? ? ? mDirtyFlags |= 0x1L;
? ? }
? ? notifyPropertyChanged(BR.contact);
? ? super.requestRebind();
}
- 其他步驟同普通?Java?bean 對象
ObservableFields 對象
- 前期步驟同普通?Java?Bean 對象
- 與 Observable 對象不同的是,Observable對象的監(jiān)聽是在 executeBindings() 中注冊的
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對象監(jiān)聽
- 入口 updateRegistration(0, contact) :
? ? return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);
}
private boolean updateRegistration(int localFieldId, Object observable,
? ? ? ? CreateWeakListener listenerCreator) {
? ? ...
? ? // 確保不重復監(jiān)聽,先移除再添加觀察監(jiān)聽
? ? unregisterFrom(localFieldId);
? ? registerTo(localFieldId, observable, listenerCreator);
? ? return true;
}
protected void registerTo(int localFieldId, Object observable,
? ? ? ? CreateWeakListener listenerCreator) {
? ? if (observable == null) {
? ? ? ? return;
? ? }
? ? // 創(chuàng)建對象監(jiān)聽并存到mLocalFieldObservers中
? ? WeakListener listener = mLocalFieldObservers[localFieldId];
? ? if (listener == null) {
? ? ? ? // CREATE_PROPERTY_LISTENER -> create(...)
? ? ? ? listener = listenerCreator.create(this, localFieldId);
? ? ? ? mLocalFieldObservers[localFieldId] = listener;
? ? }
? ? // 將監(jiān)聽綁定到Observable對象上
? ? listener.setTarget(observable);
}
每個Observable對象都會添加一個觀察監(jiān)聽,保存在數組 mLocalFieldObservers 中,并以 localFieldId 索引。
- CREATE_PROPERTY_LISTENER 為何物?
? ? @Override
? ? public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
? ? ? ? // 返回從WeakPropertyListener實例中獲取的監(jiān)聽器(WeakListener)
? ? ? ? return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
? ? }
}
private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback
? ? ? ? implements ObservableReference<Observable> {
? ? final WeakListener<Observable> 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對象的屬性監(jiān)聽器
? ? ? ? target.addOnPropertyChangedCallback(this);
? ? }
? ? ...
}
private static class WeakListener<T> extends WeakReference<ViewDataBinding> {
? ? private final ObservableReference<T> 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()方法創(chuàng)建一個弱引用listener,它的作用是將listener綁定到Observable對象上,
綁定時,會調用 listener.setTarget(…) 將Observable對象傳給 WeakPropertyListener實例,然后,WeakPropertyListener 會為 Observable對象添加OnPropertyChangedCallback。
- addOnPropertyChangedCallback實現
addOnPropertyChangedCallback 在 BaseObservable中實現,首先會實例化一個PropertyChangeRegistry對象,同時創(chuàng)建一個用來通知Observable對象重新綁定更新的回調CallbackRegistry.NotifierCallback。然后將 OnPropertyChangedCallback 添加到PropertyChangeRegistry的回調列表中
@Overridepublic synchronized void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
? ? if (mCallbacks == null) {
? ? ? ? mCallbacks = new PropertyChangeRegistry();
? ? }
? ? mCallbacks.add(callback);
}
這樣,注冊Observable對象的監(jiān)聽就完畢了。
更新(重新綁定)Observable對象
設置或更新Observable對象時都會調用notifyPropertyChanged()或notifyChange()來通知更新,那到底是如何更新的呢?
- 回調過程
? ? // mCallbacks 是 PropertyChangeRegistry對象,在 addOnPropertyChangedCallback 時實例化
? ? // 如果注冊了Observable對象監(jiān)聽,那么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時創(chuàng)建的
? ? ? ? ? ? // 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對象屬性發(fā)生變化,然后在onPropertyChanged中又轉給ViewDataBinding對象(生成的Binding類)處理。
- 判斷是否需要重新綁定并執(zhí)行,在生成的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事件的監(jiān)聽,在構造時實例化View的事件監(jiān)聽,然后在綁定時將事件監(jiān)聽對象賦值給對應View,這樣,點擊時就會觸發(fā)相應的監(jiān)聽。
這里以?DataBindingDemo?中 EventActivity部分為例:
- 生成的Binding類并實現View的事件監(jiān)聽
? ? implements Android.databinding.generated.callback.OnCheckedChangeListener.Listener,
? ? ? ? Android.databinding.generated.callback.OnClickListener.Listener {
? ? // Checkbox check監(jiān)聽
? ? 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的事件監(jiān)聽
? ? 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();
}
- 在執(zhí)行綁定中綁定View事件監(jiān)聽
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);
? ? }
}
- 觸發(fā)事件并執(zhí)行
ViewStub
原理類似,只是利用 ViewStubProxy 來延遲綁定。
- 使用layout中的ViewStub實例化一個ViewStubProxy對象賦給viewstub變量,并與Bingding關聯
? ? 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監(jiān)聽
? ? @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
? ? mActivityViewStubBinding.viewStub.getViewStub().inflate();
}
當ViewStub infate時,執(zhí)行mProxyListener,其中會生成ViewStub的Binding,并強制執(zhí)行主Binding重綁
- 綁定ViewStub
protected void executeBindings() {
? ? long dirtyFlags = 0;
? ? synchronized(this) {
? ? ? ? dirtyFlags = mDirtyFlags;
? ? ? ? mDirtyFlags = 0;
? ? }
? ? // batch finished
? ? if (viewStub.getBinding() != null) {
? ? ? ? viewStub.getBinding().executePendingBindings();
? ? }
}
這樣,ViewStub綁定就結束了。
總結
以上是生活随笔為你收集整理的Android的DataBinding原理介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTTP状态码解读
- 下一篇: JAVA微信开发:[17]如何获取所有关