一、DataBinding简介

Data binding 在2015年7⽉发布的Android Studio v1.3.0 版本上引⼊,在2016年4月Android Studio v2.0.0 上正式⽀持。⽬前为⽌,DataBinding 已经⽀持双向绑定了。Databinding 是⼀个实现数据和UI绑定的框架,是⼀个实现 MVVM 模式的⼯具,有了 Data Binding,在Android中也可以很⽅便的实现MVVM开发模式。Data Binding 是⼀个support库,最低⽀持到Android 2.1(API Level 7+)。Data Binding 的作用就是可以通过声明式布局来绑定xml,使用了DataBinding,我们就不用在java类中写findViewById、setText,setVisibility,setEnabled、setOnClickListener等这些大量重复的代码,因为DataBinding的原理实际上就是通过APT技术,在编译的时候自动帮我们把这些代码写了,我们只需要对它进行绑定就可以了,使用DataBinding能够轻松实现MVVM模式。

二、DataBinding的使用(Kotlin版)

注意:在使用DataBinding的时候,一定要在build.gradle中把DataBinding的开关打开:

dataBinding{
    enabled true
}

1、activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
       <variable
           name="user"
           type="com.yexing.databinding.User" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"
            android:textSize="40sp" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.pwd}"
            android:textSize="40sp" />
    </LinearLayout>
</layout>

2、User.kt

class User {
    val name:ObservableField<String> by lazy { ObservableField<String>() }
    val pwd:ObservableField<String> by lazy { ObservableField<String>() }
}

3、MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //绑定布局
        val bing = DataBindingUtil.setContentView<ActivityMain4Binding> 
                             (this,R.layout.activity_main4)
        //设置数据来源
        val user = User()
        user.name.set("张三")
        user.pwd.set("123456")
        bing.user = user
    }
}

三、DataBinding的源码分析

1、xml布局分析

首先,我们分析布局变化,前面已经说过,DataBinding是通过APT技术来实现的,也就是说,在我们绑定了布局并且编译之后,编译工具会自动生成一些布局相关的代码,因此,我们可以打开编译后生成的布局文件来进行分析,具体路径:build\intermediates\data_binding_layout_info_type_merge\debug\out\activity_main.xml

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Layout directory="layout" filePath="livedata\src\main\res\layout\activity_main4.xml"
    isBindingData="true" isMerge="false" layout="activity_main4"
    modulePackage="com.easygame.livedata" rootNodeType="android.widget.LinearLayout">

    <Variables name="user" declared="true" type="com.yexing.databinding.User">
        <location endLine="8" endOffset="47" startLine="6" startOffset="7" />
    </Variables>

    <Targets>
        <Target tag="layout/activity_main4_0" view="LinearLayout">
            <Expressions />
            <location endLine="26" endOffset="18" startLine="11" startOffset="4" />
        </Target>
        <Target tag="binding_1" view="TextView">
            <Expressions>
                <Expression attribute="android:text" text="user.name">
                    <Location endLine="18" endOffset="38" startLine="18" 
                        startOffset="12"/>
                    <TwoWay>false</TwoWay>
                    <ValueLocation endLine="18" endOffset="36" startLine="18" 
                        startOffset="28" />
                </Expression>
            </Expressions>
            <location endLine="19" endOffset="37" startLine="15" startOffset="8" />
        </Target>
        <Target tag="binding_2" view="TextView">
            <Expressions>
                <Expression attribute="android:text" text="user.pwd">
                    <Location endLine="24" endOffset="37" startLine="24" startOffset="12" 
                      />
                    <TwoWay>false</TwoWay>
                    <ValueLocation endLine="24" endOffset="35" startLine="24" 
                     startOffset="28" />
                </Expression>
            </Expressions>
            <location endLine="25" endOffset="37" startLine="21" startOffset="8" />
        </Target>
    </Targets>
</Layout>

可以看到,编译工具生成的布局文件定义了了多个Target标签,这些Target的定义,其实就是定义对应的tag,将tag与activity_main.xml布局中的对应的View的id对应起来经过DataBinding变化后的布局,就会有多个tag,同时打开build\intermediates\incremental\mergeDebugResources\stripped.dir\layout\activity_main.xml,我们竟然可以看到没有任何绑定的的xml布局:

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" android:tag="layout/activity_main4_0"         
                xmlns:android="http://schemas.android.com/apk/res/android" 
                xmlns:app="http://schemas.android.com/apk/res-auto" 
                xmlns:tools="http://schemas.android.com/tools">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:tag="binding_1"    
            android:textSize="40sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:tag="binding_2"   
            android:textSize="40sp" />
    </LinearLayout>
         

也就是说,DataBinding帮我们把我们在开发过程中编写的xml布局分成了两个部分,一部分是通过定义Target来把View和id关联起来,另一部分就是去掉了DataBinding的布局本身。

2、DataBindingUtil.setContentView原理

 DataBindingUtil.setContentView<ActivityMain4Binding>(this,R.layout.activity_main4)

(1)DataBindingUtil.setContentView()

点进去看源码,我们会发现,其实DataBindingUtil的setContentView方法,主要就是调用了activity的setContentView设置布局,并且绑定添加对应的View:

 public static <T extends ViewDataBinding> T setContentView(@NonNull Activity activity,
            int layoutId, @Nullable DataBindingComponent bindingComponent) {
        activity.setContentView(layoutId);
        View decorView = activity.getWindow().getDecorView();
        ViewGroup contentView = (ViewGroup) decorView.findViewById(android.R.id.content);
        return bindToAddedViews(bindingComponent, contentView, 0, layoutId);
    }
private static <T extends ViewDataBinding> T bindToAddedViews(DataBindingComponent component,
            ViewGroup parent, int startChildren, int layoutId) {
        final int endChildren = parent.getChildCount();
        final int childrenAdded = endChildren - startChildren;
        if (childrenAdded == 1) {
            final View childView = parent.getChildAt(endChildren - 1);
            return bind(component, childView, layoutId);
        } else {
            final View[] children = new View[childrenAdded];
            for (int i = 0; i < childrenAdded; i++) {
                children[i] = parent.getChildAt(i + startChildren);
            }
            return bind(component, children, layoutId);
        }
    }

(2)DataBindingUtil.bind()方法

 static <T extends ViewDataBinding> T bind(DataBindingComponent bindingComponent, View[] roots,
            int layoutId) {
        return (T) sMapper.getDataBinder(bindingComponent, roots, layoutId);
    }

这里的sMapper是一个DataBinderMapper对象,其实现类是DataBinderMapperImpl,DataBinderMapperImpl是通过apt注解处理器生成的(生成的文件目录位置:build\generated\ap_generated_sources\debug\out\包名),这里的sMapper.getDataBinder()其实就是调用了MergedDataBinderMapper的getDataBinder()方法,而sMapper中的数据,其实就是DataBinderMapperImpl的构造器中调用其父类MergedDataBinderMapper的addMapper()方法添加的对象。

public ViewDataBinding getDataBinder(DataBindingComponent component, View view, int layoutId) {
    int localizedLayoutId = INTERNAL_LAYOUT_ID_LOOKUP.get(layoutId);
    if(localizedLayoutId > 0) {
      final Object tag = view.getTag();
      if(tag == null) {
        throw new RuntimeException("view must have a tag");
      }
      switch(localizedLayoutId) {
        case  LAYOUT_ACTIVITYMAIN4: {
          if ("layout/activity_main4_0".equals(tag)) {
            return new ActivityMain4BindingImpl(component, view);
          }
          throw new IllegalArgumentException("The tag for activity_main4 is invalid. Received: " + tag);
        }
      }
    }
    return null;
  }

在getDataBinder方法里,需要注意两点,就是如果布局的顶层View,比如tag为layout/activity_main_0,那么就会new出一个ActivityMainBindingImpl对象。这个tag其实可以从前面看到的build\intermediates\incremental\mergeDebugResources\stripped.dir\layout\activity_main.xml布局中的LinearLayout的tag得知。

(3)ActivityMainBindingImpl构造器

通过apt注解器生成的ActivityMainBindingImpl这个对象,会对View进行一些绑定操作,把通过tag取出的View与ActivityMainBindingImpl中对应的View属性进行绑定。

 public ActivityMain4BindingImpl(@Nullable androidx.databinding.DataBindingComponent bindingComponent, @NonNull View root) {
        this(bindingComponent, root, mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds));
    }
 protected static Object[] mapBindings(DataBindingComponent bindingComponent, View root,
            int numBindings, IncludedLayouts includes, SparseIntArray viewsWithIds) {
        Object[] bindings = new Object[numBindings];
        mapBindings(bindingComponent, root, bindings, includes, viewsWithIds, true);
        return bindings;
    }

在这里会调用一个mapBindings方法,第三个参数的意思是布局文件下的节点数(例如我的activity_main.xml里有3个节点,而生成的是3)。这里值得注意的是,mapBindings返回的是一个Object[] bindings数组,其实就是将布局中的View保存在对应的bindings数组中,然后取出这个数组中的数据赋值给ActivityMainBindingImpl中的View,这个操作是很消耗性能的。

而ActivityMainBindingImpl的父类,其实就位置于build\generated\data_binding_base_class_source_out\debug\out\包名下:

public abstract class ActivityMain4Binding extends ViewDataBinding {
  @Bindable
  protected User mUser;

  protected ActivityMain4Binding(Object _bindingComponent, View _root, int _localFieldCount) {
    super(_bindingComponent, _root, _localFieldCount);
  }

  public abstract void setUser(@Nullable User user);

  @Nullable
  public User getUser() {
    return mUser;
  }
...
}

4、ActivityMainBinding.setUser解析 

(1)BR文件

public class BR {
  public static final int _all = 0;

  public static final int user = 1;
}

BR文件位于build\generated\ap_generated_sources\debug\out\包名下,其作用是定义不同的属性值来标记不同的操作需要的监听在mLocalFieldObservers数组中的位置。

(2)ActivityMain4BindingImpl.setUser()

 public void setUser(@Nullable com.yexing.databinding.User User) {
        this.mUser = User;
        synchronized(this) {
            mDirtyFlags |= 0x4L;
        }
         //通知user保存数据
        notifyPropertyChanged(BR.user);
        super.requestRebind();
    }

(3)ViewDataBind.updateRegistration()

 private boolean updateRegistration(int localFieldId, Object observable,
            CreateWeakListener listenerCreator) {
        if (observable == null) {
            return unregisterFrom(localFieldId);
        }
        WeakListener listener = mLocalFieldObservers[localFieldId];
        if (listener == null) {
            registerTo(localFieldId, observable, listenerCreator);
            return true;
        }
         //根据BR的每个属性的属性值做index,存储每个BR属性对应的监听器
        if (listener.getTarget() == observable) {
            return false;//nothing to do, same object
        }
        unregisterFrom(localFieldId);
        registerTo(localFieldId, observable, listenerCreator);
        return true;
    }


 //这个方法其实就是将Activity这个观察者和User这个被观察者统一添加到ObservableFeference中
 protected void registerTo(int localFieldId, Object observable,
            CreateWeakListener listenerCreator) {
        if (observable == null) {
            return;
        }
        WeakListener listener = mLocalFieldObservers[localFieldId];
        if (listener == null) {
            //通过属性监听器的创建器创建一个BR属性值对应的监听器
            listener = listenerCreator.create(this, localFieldId);
            mLocalFieldObservers[localFieldId] = listener;
            //将监听器与观察者做绑定,这里的观察者其实就是activity
            if (mLifecycleOwner != null) {
                listener.setLifecycleOwner(mLifecycleOwner);
            }
        }
        //将监听器与被观察者做绑定,被观察者是User
        listener.setTarget(observable);
    }

这里通过WeakListener监听器中的ObservableReference对象保存观察者与被观察者,当被观察者发生改变的时候,就会找到对应的WeakListener监听器,然后通知观察者做修改。这里的listner.setTarget()其实就是通过WeakPropertyListener给被观察者添加callback,然后当被观察者数据发生改变的时候,被观察者通过遍历其内部的PropertyChangeRegistry中的OnPropertyChangedCallback回调,然后通过WeakPropertyListener监听通知给ViewDataBinding以及其实现类ActivityMainBindImpl具体进行数据的处理和设置。

(4)WeakListener.setTarget()

 public void setTarget(T object) {
            unregister();
            mTarget = object;
            if (mTarget != null) {
                mObservable.addListener(mTarget);
            }
        }

这里的mTarget是一个泛型对象,这个泛型是在WeakPropertyListener初始化WeakListener的时候传入的一个Observable,这个是databinding中的Observable,其子类实现就是BaseObservable。WeakPropertyListener中的addListener方法会给Observable添加一个callback回调,向Observable这个被观察者中添加callback的目的,就是在Observable数据发生变化的时候,遍历Observable中的mCallbacks这个集合,通知观察者进行修改,这个操作也是相当消耗性能的。

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) {
            target.addOnPropertyChangedCallback(this);
        }

        @Override
        public void removeListener(Observable target) {
            target.removeOnPropertyChangedCallback(this);
        }

        @Override
        public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
        }

        @Override
        public void onPropertyChanged(Observable sender, int propertyId) {
            ViewDataBinding binder = mListener.getBinder();
            if (binder == null) {
                return;
            }
            Observable obj = mListener.getTarget();
            if (obj != sender) {
                return; // notification from the wrong object?
            }
            binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
        }
    }

BaseObservable这个被观察者会被WeakListener持有,而WeakListener会被WeakPropertyListener持有,从而BaseObservable会间接的被WeakPropertyListener持有。而BaseObservable会通过mCallbacks持有Observable.OnPropertyChangedCallback对象,而Observable.OnPropertyChangedCallback的子类是WeakPropertyListener,所以BaseObservable也会持有WeakPropertyListener对象。而WeakPropertyListener和WeakListener是相互持有的,在完成监听并且给Observable添加了回调之后,就会回到ActivityMainBindImpl的setUser()方法继续执行notifyPropertyChanged()方法。

(5)Observable.notifyPropertyChanged()方法

 /**
     * Notifies listeners that a specific property has changed. The getter for the property
     * that changes should be marked with {@link Bindable} to generate a field in
     * <code>BR</code> to be used as <code>fieldId</code>.
     *
     * @param fieldId The generated BR id for the Bindable field.
     */
    public void notifyPropertyChanged(int fieldId) {
        synchronized (this) {
            if (mCallbacks == null) {
                return;
            }
        }
        mCallbacks.notifyCallbacks(this, fieldId, null);
    }
/**
     * Notify all callbacks.
     *
     * @param sender The originator. This is an opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param arg An opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param arg2 An opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     */
    public synchronized void notifyCallbacks(T sender, int arg, A arg2) {
        mNotificationLevel++;
        notifyRecurse(sender, arg, arg2);
        mNotificationLevel--;
        if (mNotificationLevel == 0) {
            if (mRemainderRemoved != null) {
                for (int i = mRemainderRemoved.length - 1; i >= 0; i--) {
                    final long removedBits = mRemainderRemoved[i];
                    if (removedBits != 0) {
                        removeRemovedCallbacks((i + 1) * Long.SIZE, removedBits);
                        mRemainderRemoved[i] = 0;
                    }
                }
            }
            if (mFirst64Removed != 0) {
                removeRemovedCallbacks(0, mFirst64Removed);
                mFirst64Removed = 0;
            }
        }
    }

    /**
     * Notify up to the first Long.SIZE callbacks that don't have a bit set in <code>removed</code>.
     *
     * @param sender The originator. This is an opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param arg An opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param arg2 An opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     */
    private void notifyFirst64(T sender, int arg, A arg2) {
        final int maxNotified = Math.min(Long.SIZE, mCallbacks.size());
        notifyCallbacks(sender, arg, arg2, 0, maxNotified, mFirst64Removed);
    }

    /**
     * Notify all callbacks using a recursive algorithm to avoid allocating on the heap.
     * This part captures the callbacks beyond Long.SIZE that have no bits allocated for
     * removal before it recurses into {@link #notifyRemainder(Object, int, A, int)}.
     *
     * <p>Recursion is used to avoid allocating temporary state on the heap.</p>
     *
     * @param sender The originator. This is an opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param arg An opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param arg2 An opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     */
    private void notifyRecurse(T sender, int arg, A arg2) {
        final int callbackCount = mCallbacks.size();
        final int remainderIndex = mRemainderRemoved == null ? -1 : mRemainderRemoved.length - 1;

        // Now we've got all callbakcs that have no mRemainderRemoved value, so notify the
        // others.
        notifyRemainder(sender, arg, arg2, remainderIndex);

        // notifyRemainder notifies all at maxIndex, so we'd normally start at maxIndex + 1
        // However, we must also keep track of those in mFirst64Removed, so we add 2 instead:
        final int startCallbackIndex = (remainderIndex + 2) * Long.SIZE;

        // The remaining have no bit set
        notifyCallbacks(sender, arg, arg2, startCallbackIndex, callbackCount, 0);
    }

    /**
     * Notify callbacks that have mRemainderRemoved bits set for remainderIndex. If
     * remainderIndex is -1, the first 64 will be notified instead.
     *
     * @param sender The originator. This is an opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param arg An opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param arg2 An opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param remainderIndex The index into mRemainderRemoved that should be notified.
     */
    private void notifyRemainder(T sender, int arg, A arg2, int remainderIndex) {
        if (remainderIndex < 0) {
            notifyFirst64(sender, arg, arg2);
        } else {
            final long bits = mRemainderRemoved[remainderIndex];
            final int startIndex = (remainderIndex + 1) * Long.SIZE;
            final int endIndex = Math.min(mCallbacks.size(), startIndex + Long.SIZE);
            notifyRemainder(sender, arg, arg2, remainderIndex - 1);
            notifyCallbacks(sender, arg, arg2, startIndex, endIndex, bits);
        }
    }

    /**
     * Notify callbacks from startIndex to endIndex, using bits as the bit status
     * for whether they have been removed or not. bits should be from mRemainderRemoved or
     * mFirst64Removed. bits set to 0 indicates that all callbacks from startIndex to
     * endIndex should be notified.
     *
     * @param sender The originator. This is an opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param arg An opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param arg2 An opaque parameter passed to
     * {@link CallbackRegistry.NotifierCallback#onNotifyCallback(Object, Object, int, Object)}
     * @param startIndex The index into the mCallbacks to start notifying.
     * @param endIndex One past the last index into mCallbacks to notify.
     * @param bits A bit field indicating which callbacks have been removed and shouldn't
     *             be notified.
     */
    private void notifyCallbacks(T sender, int arg, A arg2, final int startIndex,
            final int endIndex, final long bits) {
        long bitMask = 1;
        for (int i = startIndex; i < endIndex; i++) {
            if ((bits & bitMask) == 0) {
                mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg, arg2);
            }
            bitMask <<= 1;
        }
    }

这里的mNotifyer.notifyCallback其实就会调用到下面的PropertyChangeRegistry中定义的NOTIFYER_CALLBACK属性中的onNotifyCallback实现,而这里的callback其实就是WeakPropertyListener,因为WeakPropertyListener是OnPropertyChangedCallback的子类,这里会回调给mLocalFieldObservers数组中所有的WeakListener。

public class PropertyChangeRegistry extends
        CallbackRegistry<Observable.OnPropertyChangedCallback, Observable, Void> {

    private static final CallbackRegistry.NotifierCallback<Observable.OnPropertyChangedCallback, Observable, Void> NOTIFIER_CALLBACK = new CallbackRegistry.NotifierCallback<Observable.OnPropertyChangedCallback, Observable, Void>() {
        @Override
        public void onNotifyCallback(Observable.OnPropertyChangedCallback callback, Observable sender,
                int arg, Void notUsed) {
            callback.onPropertyChanged(sender, arg);
        }
    };

    public PropertyChangeRegistry() {
        super(NOTIFIER_CALLBACK);
    }

    /**
     * Notifies registered callbacks that a specific property has changed.
     *
     * @param observable The Observable that has changed.
     * @param propertyId The BR id of the property that has changed or BR._all if the entire
     *                   Observable has changed.
     */
    public void notifyChange(@NonNull Observable observable, int propertyId) {
        notifyCallbacks(observable, propertyId, null);
    }
}

而这里的callback.onPropertyChanged(sender, arg);则会回调到ViewDataBinding类中的WeakPropertyListener.onPropertyChanged:

 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) {
            target.addOnPropertyChangedCallback(this);
        }

        @Override
        public void removeListener(Observable target) {
            target.removeOnPropertyChangedCallback(this);
        }

        @Override
        public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
        }

        @Override
        public void onPropertyChanged(Observable sender, int propertyId) {
            ViewDataBinding binder = mListener.getBinder();
            if (binder == null) {
                return;
            }
            Observable obj = mListener.getTarget();
            if (obj != sender) {
                return; // notification from the wrong object?
            }
            binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
        }
    }

从mListener中取出target,而这里的mListener其实就是WeakListener,而每个被观察者,其实都 是有一个对应的LocalFieldId,这个id就是BR文件中定义中的id。

private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
        if (mInLiveDataRegisterObserver) {
            // We're in LiveData registration, which always results in a field change
            // that we can ignore. The value will be read immediately after anyway, so
            // there is no need to be dirty.
            return;
        }
        boolean result = onFieldChange(mLocalFieldId, object, fieldId);
        if (result) {
            requestRebind();
        }
    }

这里的handleFieldChange方法,在我们生成的ActivityMainBindingImpl也有实现:

@Override
    protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
        switch (localFieldId) {
            case 0 :
                return onChangeUserName((androidx.databinding.ObservableField<java.lang.String>) object, fieldId);
            case 1 :
                return onChangeUserPwd((androidx.databinding.ObservableField<java.lang.String>) object, fieldId);
        }
        return false;
    }
    private boolean onChangeUserName(androidx.databinding.ObservableField<java.lang.String> UserName, int fieldId) {
        if (fieldId == BR._all) {
            synchronized(this) {
                    mDirtyFlags |= 0x1L;
            }
            return true;
        }
        return false;
    }
    private boolean onChangeUserPwd(androidx.databinding.ObservableField<java.lang.String> UserPwd, int fieldId) {
        if (fieldId == BR._all) {
            synchronized(this) {
                    mDirtyFlags |= 0x2L;
            }
            return true;
        }
        return false;
    }

因为我们之前传入的localFieldId = 0,所以会返回true,即会返回到ViewDataBinding.java中的handleFieldChange方法,继续执行requestRebind():

private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
        if (mInLiveDataRegisterObserver) {
            // We're in LiveData registration, which always results in a field change
            // that we can ignore. The value will be read immediately after anyway, so
            // there is no need to be dirty.
            return;
        }
        boolean result = onFieldChange(mLocalFieldId, object, fieldId);
        if (result) {
            requestRebind();
        }
    }



protected void requestRebind() {
        if (mContainingBinding != null) {
            mContainingBinding.requestRebind();
        } else {
            final LifecycleOwner owner = this.mLifecycleOwner;
            if (owner != null) {
                Lifecycle.State state = owner.getLifecycle().getCurrentState();
                if (!state.isAtLeast(Lifecycle.State.STARTED)) {
                    return; // wait until lifecycle owner is started
                }
            }
            synchronized (this) {
                if (mPendingRebind) {
                    return;
                }
                mPendingRebind = true;
            }
            if (USE_CHOREOGRAPHER) {
                mChoreographer.postFrameCallback(mFrameCallback);
            } else {
                mUIThreadHandler.post(mRebindRunnable);
            }
        }
    }

这里最终会通过mUIThreadHandler.post(mRebindRunnable);执行mRebindRunnable里面的run方法:

 /**
     * Runnable executed on animation heartbeat to rebind the dirty Views.
     */
    private final Runnable mRebindRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (this) {
                mPendingRebind = false;
            }
            processReferenceQueue();

            if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
                // Nested so that we don't get a lint warning in IntelliJ
                if (!mRoot.isAttachedToWindow()) {
                    // Don't execute the pending bindings until the View
                    // is attached again.
                    mRoot.removeOnAttachStateChangeListener(ROOT_REATTACHED_LISTENER);
                    mRoot.addOnAttachStateChangeListener(ROOT_REATTACHED_LISTENER);
                    return;
                }
            }
            executePendingBindings();
        }
    };

然后执行到executePendingBindings()方法,而方法的实现又是在我们生成的MainActivityBindingImpl里:

 @Override
    protected void executeBindings() {
        long dirtyFlags = 0;
        synchronized(this) {
            dirtyFlags = mDirtyFlags;
            mDirtyFlags = 0;
        }
        androidx.databinding.ObservableField<java.lang.String> userName = null;
        java.lang.String userPwdGet = null;
        com.yexing.databinding.User user = mUser;
        java.lang.String userNameGet = null;
        androidx.databinding.ObservableField<java.lang.String> userPwd = null;

        if ((dirtyFlags & 0xfL) != 0) {


            if ((dirtyFlags & 0xdL) != 0) {

                    if (user != null) {
                        // read user.name
                        userName = user.getName();
                    }
                    updateRegistration(0, userName);


                    if (userName != null) {
                        // read user.name.get()
                        userNameGet = userName.get();
                    }
            }
            if ((dirtyFlags & 0xeL) != 0) {

                    if (user != null) {
                        // read user.pwd
                        userPwd = user.getPwd();
                    }
                    updateRegistration(1, userPwd);


                    if (userPwd != null) {
                        // read user.pwd.get()
                        userPwdGet = userPwd.get();
                    }
            }
        }
        // batch finished
        if ((dirtyFlags & 0xdL) != 0) {
            // api target 1

            androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView1, userNameGet);
        }
        if ((dirtyFlags & 0xeL) != 0) {
            // api target 1

            androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView2, userPwdGet);
        }
    }

这个方法其实就是执行了setText操作,也就是调用了页面布局的View的setText把数据显示出来。到此,DataBinding的源码分析完成。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐