寫在前面
上篇文章 Android Data Binding 系列(一) -- 詳細(xì)介紹與使用 介紹了 Data Binding
的基礎(chǔ)及其用法遍蟋,本文接上篇浅妆,結(jié)合DataBindingDemo 來學(xué)習(xí)下 Data Binding
的實(shí)現(xiàn)剃毒。
綁定實(shí)現(xiàn)
Activity在inflate layout時(shí)胰坟,通過DataBindingUtil來生成綁定涕侈,從代碼看,是遍歷contentView得到View數(shù)組對(duì)象秒旋,然后通過數(shù)據(jù)綁定library生成對(duì)應(yīng)的Binding類,含Views诀拭、變量迁筛、listeners等。生成類位于
build/intermediates/classes/debug/...package.../databinding/xxx.java
下,具體如何生成這里暫不作深入细卧。
綁定過程
- 首先尉桩,會(huì)在父類(ViewDataBinding)中實(shí)例化回調(diào)或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());
}
- 接著蜘犁,通過調(diào)用
mapBindings(...)
遍歷布局以獲得包含bound、includes止邮、ID Views的數(shù)組對(duì)象这橙,再依次賦給對(duì)應(yīng)View
final Object[] bindings = mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds);
this.mboundView0 = (android.widget.LinearLayout) bindings[0];
this.mboundView0.setTag(null);
- 然后,調(diào)用
invalidateAll() -> requestRebind() -> ... -> mRebindRunnable.run() -
執(zhí)行 Runnable
// 用于動(dòng)態(tài)重新綁定 Views
private final Runnable mRebindRunnable = new Runnable() {
@Override
public void run() {
synchronized (this) {
mPendingRebind = false;
}
.....
executePendingBindings();
}
};
- 最后导披,通過該Runnable會(huì)執(zhí)行到
executePendingBindings() -> ... -> executeBindings()
屈扎,在這里會(huì)執(zhí)行綁定相關(guān)操作。
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags; // mDirtyFlags 變量更新的標(biāo)志
mDirtyFlags = 0;
}
.....
}
設(shè)置變量(數(shù)據(jù)對(duì)象)
普通 Java bean 對(duì)象
- 首先撩匕,通過mDirtyFlags標(biāo)識(shí)變量(所有變量共用)
synchronized(this) {
mDirtyFlags |= 0x1L;
}
- 然后鹰晨,調(diào)用
notifyPropertyChanged(...)
來通知更新(若有回調(diào))
public void notifyPropertyChanged(int fieldId) {
if (mCallbacks != null) {
mCallbacks.notifyCallbacks(this, fieldId, null);
}
}
- 最后,調(diào)用
requestRebind() -> ... -> executeBindings()
再次執(zhí)行綁定操作止毕,將數(shù)據(jù)更新到Views上
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
.....
}
Observable 對(duì)象
- 在設(shè)置變量時(shí)模蜡,會(huì)先調(diào)用
updateRegistration(..)
注冊(cè)一個(gè)Observable對(duì)象的監(jiān)聽
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 對(duì)象
ObservableFields 對(duì)象
前期步驟同普通 Java Bean 對(duì)象
與 Observable 對(duì)象不同的是,Observable對(duì)象的監(jiān)聽是在
executeBindings()
中注冊(cè)的
@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();
}
}
...
}
...
}
注冊(cè)O(shè)bservable對(duì)象監(jiān)聽
- 入口
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) {
...
// 確保不重復(fù)監(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)建對(duì)象監(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對(duì)象上
listener.setTarget(observable);
}
每個(gè)Observable對(duì)象都會(huì)添加一個(gè)觀察監(jiān)聽忍疾,保存在數(shù)組 mLocalFieldObservers
中,并以 localFieldId
索引令漂。
- CREATE_PROPERTY_LISTENER 為何物膝昆?
private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
@Override
public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
// 返回從WeakPropertyListener實(shí)例中獲取的監(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 其實(shí)就是 Observable對(duì)象的屬性監(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對(duì)象
// mTarget 是綁定到listener上得Observable對(duì)象
mObservable.addListener(mTarget);
}
}
...
}
CREATE_PROPERTY_LISTENER 實(shí)際上只是一個(gè)接口實(shí)例叠必,注冊(cè)時(shí)會(huì)調(diào)用它的create()
方法創(chuàng)建一個(gè)弱引用listener荚孵,它的作用是將listener綁定到Observable對(duì)象上,
綁定時(shí)纬朝,會(huì)調(diào)用 listener.setTarget(...)
將Observable對(duì)象傳給 WeakPropertyListener
實(shí)例收叶,然后,WeakPropertyListener
會(huì)為 Observable對(duì)象添加OnPropertyChangedCallback
共苛。
- addOnPropertyChangedCallback實(shí)現(xiàn)
addOnPropertyChangedCallback 在 BaseObservable中實(shí)現(xiàn)判没,首先會(huì)實(shí)例化一個(gè)PropertyChangeRegistry
對(duì)象,同時(shí)創(chuàng)建一個(gè)用來通知Observable對(duì)象重新綁定更新的回調(diào)CallbackRegistry.NotifierCallback
隅茎。然后將 OnPropertyChangedCallback
添加到PropertyChangeRegistry的回調(diào)列表中
@Override
public synchronized void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
if (mCallbacks == null) {
mCallbacks = new PropertyChangeRegistry();
}
mCallbacks.add(callback);
}
這樣澄峰,注冊(cè)O(shè)bservable對(duì)象的監(jiān)聽就完畢了。
更新(重新綁定)Observable對(duì)象
設(shè)置或更新Observable對(duì)象時(shí)都會(huì)調(diào)用notifyPropertyChanged()
或notifyChange()
來通知更新辟犀,那到底是如何更新的呢俏竞?
- 回調(diào)過程
public void notifyPropertyChanged(int fieldId) {
// mCallbacks 是 PropertyChangeRegistry對(duì)象,在 addOnPropertyChangedCallback 時(shí)實(shí)例化
// 如果注冊(cè)了Observable對(duì)象監(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 是實(shí)例化PropertyChangeRegistry時(shí)創(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對(duì)象添加的OnPropertyChangedCallback魂毁,即WeakPropertyListener
callback.onPropertyChanged(sender, arg);
}
// WeakPropertyListener
public void onPropertyChanged(Observable sender, int propertyId) {
// binder 即生成的Binding類對(duì)象
ViewDataBinding binder = mListener.getBinder();
...
binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
}
private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
// onFieldChange 實(shí)現(xiàn)在生成的Binding類中
boolean result = onFieldChange(mLocalFieldId, object, fieldId);
if (result) {
// 如果對(duì)象屬性變化玻佩,將重新綁定
requestRebind();
}
}
通過 notifyPropertyChanged 調(diào)用到 mNotifier 回調(diào), mNotifier 通知OnPropertyChangedCallback
Observable對(duì)象屬性發(fā)生變化席楚,然后在onPropertyChanged
中又轉(zhuǎn)給ViewDataBinding對(duì)象(生成的Binding類)處理咬崔。
- 判斷是否需要重新綁定并執(zhí)行,在生成的Binding類中實(shí)現(xiàn)
// 生成的Binding類中得方法
protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
// 如果變量不是Observable類型或沒有添加 Bindable注解烦秩,就不會(huì)判斷垮斯,直接返回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判斷對(duì)象是否變化
}
return true;
}
...
}
return false;
}
至此,更新過程完畢闻镶。
整個(gè)注冊(cè)與更新過程可以用一張流程圖來概括:
事件處理
事件處理的原理很簡(jiǎn)單甚脉,在生成Binding類中會(huì)實(shí)現(xiàn)View事件的監(jiān)聽,在構(gòu)造時(shí)實(shí)例化View的事件監(jiān)聽铆农,然后在綁定時(shí)將事件監(jiān)聽對(duì)象賦值給對(duì)應(yīng)View牺氨,這樣,點(diǎn)擊時(shí)就會(huì)觸發(fā)相應(yīng)的監(jiān)聽墩剖。
這里以 DataBindingDemo 中 EventActivity
部分為例:
- 生成的Binding類并實(shí)現(xiàn)View的事件監(jiān)聽
public class ActivityEventBinding extends android.databinding.ViewDataBinding
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);
}
}
...
}
- 實(shí)例化View的事件監(jiān)聽
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();
}
- 在執(zhí)行綁定中綁定View事件監(jiān)聽
@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);
}
}
- 觸發(fā)事件并執(zhí)行
ViewStub
原理類似猴凹,只是利用 ViewStubProxy
來延遲綁定。
- 使用layout中的ViewStub實(shí)例化一個(gè)ViewStubProxy對(duì)象賦給viewstub變量岭皂,并與Bingding關(guān)聯(lián)
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);
...
}
- 實(shí)例化ViewStubProxy的同時(shí)會(huì)注冊(cè)inflate監(jiān)聽
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();
}
當(dāng)ViewStub infate時(shí)郊霎,執(zhí)行mProxyListener
,其中會(huì)生成ViewStub的Binding爷绘,并強(qiáng)制執(zhí)行主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綁定就結(jié)束了。
本篇完土至,敬請(qǐng)期待下篇...
我的簡(jiǎn)書賬號(hào)是 ConnorLin购对,歡迎關(guān)注!
我的簡(jiǎn)書專題是 Android開發(fā)技術(shù)分享陶因,歡迎關(guān)注骡苞!