Android的DataBinding原理介绍详解手机开发

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(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.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<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 其实就是 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不为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 是实例化PropertyChangeRegistry时创建的
           
// 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对象添加的OnPropertyChangedCallback,即WeakPropertyListener
    callback
.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注解,就不会判断,直接返回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判断对象是否变化
           
}
           
return true;
       
}
       
...
   
}
   
return false;
}

至此,更新过程完毕。

整个注册与更新过程可以用一张流程图来概括:

Android Data Binding 系列(二) -- Binding与Observer实现原理

事件处理

事件处理的原理很简单,在生成Binding类中会实现View事件的监听,在构造时实例化View的事件监听,然后在绑定时将事件监听对象赋值给对应View,这样,点击时就会触发相应的监听。

这里以 DataBindingDemo 中 EventActivity部分为例:

  • 生成的Binding类并实现View的事件监听
public class ActivityEventBinding extends Android.databinding.ViewDataBinding
   
implements 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;
   
// 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);
       
}
   
}
   
...
}
  • 实例化View的事件监听
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
();
}
  • 在执行绑定中绑定View事件监听
@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);
   
}
}
  • 触发事件并执行

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() {
   
@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();
}

当ViewStub infate时,执行mProxyListener,其中会生成ViewStub的Binding,并强制执行主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绑定就结束了。

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/5839.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论