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
// 用于动态重新绑定 Viewsprivate final Runnable mRebindRunnable = new Runnable() { @Override public void run() { synchronized (this) { mPendingRebind = false; } ..... executePendingBindings(); }};
- 最后,通过该Runnable会执行到 executePendingBindings() -> … -> executeBindings(),在这里会执行绑定相关操作。
@Overrideprotected 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上
@Overrideprotected 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() 中注册的
@Overrideprotected 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(binder, localFieldId, this); } @Override public WeakListener 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的回调列表中
@Overridepublic 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); }}// baseLibraryprivate void notifyCallbacks(T sender, int arg, A arg2, int startIndex, int endIndex, long bits) { long bitMask = 1L; for(int i = startIndex; i关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?