写在前面
上篇文章 Android Data Binding 系列(一) – 详细介绍与使用 介绍了 Data Binding
的基础及其用法,本文接上篇,结合DataBindingDemo 来学习下 Data Binding
的实现。
绑定实现
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(...)
遍历布局以获得包含bound、includes、ID 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标识变量(所有变量共用)
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</