写在前面
上篇文章 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,用于之后的绑定操作;
1 | private static final boolean USE_CHOREOGRAPHER = SDK_INT >= 16; |
- 接着,通过调用
mapBindings(...)
遍历布局以获得包含bound、includes、ID Views的数组对象,再依次赋给对应View
1 | final Object[] bindings = mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds); |
- 然后,调用
invalidateAll() -> requestRebind() -> ... -> mRebindRunnable.run() -
执行 Runnable
1 | // 用于动态重新绑定 Views |
- 最后,通过该Runnable会执行到
executePendingBindings() -> ... -> executeBindings()
,在这里会执行绑定相关操作。
1 |
|
设置变量(数据对象)
普通 Java bean 对象
- 首先,通过mDirtyFlags标识变量(所有变量共用)
1 | synchronized(this) { |
- 然后,调用
notifyPropertyChanged(...)
来通知更新(若有回调)
1 | public void notifyPropertyChanged(int fieldId) { |
- 最后,调用
requestRebind() -> ... -> executeBindings()
再次执行绑定操作,将数据更新到Views上
1 |
|
Observable 对象
- 在设置变量时,会先调用
updateRegistration(..)
注册一个Observable对象的监听
1 | public void setContact(com.connorlin.databinding.model.ObservableContact contact) { |
- 其他步骤同普通 Java bean 对象
ObservableFields 对象
前期步骤同普通 Java Bean 对象
与 Observable 对象不同的是,Observable对象的监听是在
executeBindings()
中注册的
1 |
|
注册Observable对象监听
- 入口
updateRegistration(0, contact)
:
1 | protected boolean updateRegistration(int localFieldId, Observable observable) { |
每个Observable对象都会添加一个观察监听,保存在数组 mLocalFieldObservers
中,并以 localFieldId
索引。
- CREATE_PROPERTY_LISTENER 为何物?
1 | private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() { |
CREATE_PROPERTY_LISTENER 实际上只是一个接口实例,注册时会调用它的create()
方法创建一个弱引用listener,它的作用是将listener绑定到Observable对象上,
绑定时,会调用 listener.setTarget(...)
将Observable对象传给 WeakPropertyListener
实例,然后,WeakPropertyListener
会为 Observable对象添加OnPropertyChangedCallback
。
- addOnPropertyChangedCallback实现
addOnPropertyChangedCallback 在 BaseObservable中实现,首先会实例化一个PropertyChangeRegistry
对象,同时创建一个用来通知Observable对象重新绑定更新的回调CallbackRegistry.NotifierCallback
。然后将 OnPropertyChangedCallback
添加到PropertyChangeRegistry的回调列表中
1 |
|
这样,注册Observable对象的监听就完毕了。
更新(重新绑定)Observable对象
设置或更新Observable对象时都会调用notifyPropertyChanged()
或notifyChange()
来通知更新,那到底是如何更新的呢?
- 回调过程
1 | public void notifyPropertyChanged(int fieldId) { |
通过 notifyPropertyChanged 调用到 mNotifier 回调, mNotifier 通知OnPropertyChangedCallback
Observable对象属性发生变化,然后在onPropertyChanged
中又转给ViewDataBinding对象(生成的Binding类)处理。
- 判断是否需要重新绑定并执行,在生成的Binding类中实现
1 | // 生成的Binding类中得方法 |
至此,更新过程完毕。
整个注册与更新过程可以用一张流程图来概括:
事件处理
事件处理的原理很简单,在生成Binding类中会实现View事件的监听,在构造时实例化View的事件监听,然后在绑定时将事件监听对象赋值给对应View,这样,点击时就会触发相应的监听。
这里以 DataBindingDemo 中 EventActivity
部分为例:
- 生成的Binding类并实现View的事件监听
1 | public class ActivityEventBinding extends android.databinding.ViewDataBinding |
- 实例化View的事件监听
1 | public ActivityEventBinding(android.databinding.DataBindingComponent bindingComponent, View root) { |
- 在执行绑定中绑定View事件监听
1 |
|
- 触发事件并执行
ViewStub
原理类似,只是利用 ViewStubProxy
来延迟绑定。
- 使用layout中的ViewStub实例化一个ViewStubProxy对象赋给viewstub变量,并与Bingding关联
1 | public ActivityViewStubBinding(android.databinding.DataBindingComponent bindingComponent, View root) { |
- 实例化ViewStubProxy的同时会注册inflate监听
1 | private OnInflateListener mProxyListener = new OnInflateListener() { |
- inflate ViewStub
1 | if (!mActivityViewStubBinding.viewStub.isInflated()) { |
当ViewStub infate时,执行mProxyListener
,其中会生成ViewStub的Binding,并强制执行主Binding重绑
- 绑定ViewStub
1 |
|
这样,ViewStub绑定就结束了。
本篇完,敬请期待下篇…
我的简书账号是 ConnorLin,欢迎关注!
我的简书专题是 Android开发技术分享,欢迎关注!
我的个人博客 欢迎关注!
原创文章,欢迎转载,转载请注明出处!