写在前面
上篇文章 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() {
@Overridepublic 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() {
@Overridepublic 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(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.mNamemNameContact = 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() {
@Overridepublic WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
// 返回从WeakPropertyListener实例中获取的监听器(WeakListener)return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();} }private static class WeakPropertyListener extends Observable.OnPropertyChangedCallbackimplements ObservableReference<Observable> {
final WeakListener<Observable> mListener;public WeakPropertyListener(ViewDataBinding binder, int localFieldId) {
mListener = new WeakListener<Observable>(binder, localFieldId, this);}@Overridepublic WeakListener<Observable> getListener() {
return mListener;}@Overridepublic void addListener(Observable target) {
// WeakPropertyListener 继承于 Observable.OnPropertyChangedCallback,// 所以 this 其实就是 Observable对象的属性监听器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()
方法创建一个弱引用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不为nullif (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.NotifierCallbackthis.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,即WeakPropertyListenercallback.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注解,就不会判断,直接返回falseswitch (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.ViewDataBindingimplements 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;// listenersprivate OnClickListenerImpl mAndroidViewViewOnCl;...// Listener Stub Implementationspublic 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;}@Overridepublic void onClick(android.view.View arg0) {
this.value.onClickFriend(arg0);}}... }
- 实例化View的事件监听
public ActivityEventBinding(android.databinding.DataBindingComponent bindingComponent, View root) {
super(bindingComponent, root, 0);...// listenersmCallback3 = 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::onClickFriendandroidViewViewOnCli = (((mAndroidViewViewOnCl == null)? (mAndroidViewViewOnCl = new OnClickListenerImpl()) : mAndroidViewViewOnCl).setValue(handler));}}// batch finishedif ((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变量,并与Bingding关联
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() {
@Overridepublic 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 finishedif (viewStub.getBinding() != null) {
viewStub.getBinding().executePendingBindings();} }
这样,ViewStub绑定就结束了。