一.前言
- 本篇文章主要按照三个方面来讲,使用Databinding之后为什么不需要findViewById,Model驱动UI的模型是如何设计的;View改变是如何驱动Model变化的;
二.Databinding简介
2.1.核心思想
- 当数据发生变化时,UI 自动更新;当用户与 UI 交互时,数据自动同步;
2.2.作用
- 不需要findViewById;
- 能承担activity、fragment的部分简单逻辑;
- 解耦(架构上促进了UI跟逻辑的分离,是 MVVM 的基石);
三.源码分析
- 我们借助下方代码示例,来分析在前言中所提到的问题,代码如下:
//MainActivity类
public class MainActivity extends AppCompatActivity {
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
User user = new User("张三","15");
binding.setUser(user);
// binding.setVariable(BR.name,"李四");
}
}
//User类
public class User extends BaseObservable {
private String name;
private String age;
public User(String name, String age) {
this.name = name;
this.age = age;
}
@Bindable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
@Bindable
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
notifyPropertyChanged(BR.age);
}
}
//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.jack.databinding.User" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.name}" />
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.age}" />
</LinearLayout>
</layout>
3.1.为什么使用databinding之后,不需要做findViewbyId
-
在分析之前,我们先看databinding生成的2个Java文件和2个xml文件;
- ActivityMainBindingImpl.java和ActivityMainBinding.java,其中ActivityMainBindingImpl继承自ActivityMainBinding的实现类,ActivityMainBinding继承自ViewDataBinding类(ActivityMainBinding和ViewDataBinding均为抽象类,ViewDataBinding是Datbinding框架中的);
- activity_main.xml和activity_main-layout.xml;这两份xml文件组合来描述我们所写的xml代码,一份(activity_main.xml)在布局的每一个节点增加了一个TAG,另外一份(activity_main-layout.xml)中TAG跟View有对应关系 & 有 Ex’pressions 标签,该标签描述数据相关的内容(属性对应的内容);
-
ActivityMainBindingImpl.java,参考路径:
xxx\app\build\generated\ap_generated_sources\debug\out\com\jack\databinding\databinding\ActivityMainBindingImpl.java
- ActivityMainBinding.java,参考路径:
xxx\app\build\generated\data_binding_base_class_source_out\debug\out\com\jack\databinding\databinding\ActivityMainBinding.java
- activity_main.xml,参考路径和代码:
xxx\build\intermediates\incremental\debug\packageDebugResources\stripped.dir\layout\activity_main.xml
//代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:tag="layout/activity_main_0">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="binding_1" />
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="binding_2" />
</LinearLayout>
- activity_main-layout.xml,参考路径和代码:
//路径
xxx\app\build\intermediates\data_binding_layout_info_type_merge\debug\mergeDebugResources\out\activity_main-layout.xml
//代码
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Layout directory="layout" filePath="app\src\main\res\layout\activity_main.xml"
isBindingData="true" isMerge="false" layout="activity_main"
modulePackage="com.jack.databinding" rootNodeType="android.widget.LinearLayout">
<Variables name="user" declared="true" type="com.jack.databinding.User">
<location endLine="7" endOffset="46" startLine="5" startOffset="8" />
</Variables>
<Targets>
<Target tag="layout/activity_main_0" view="LinearLayout">
<Expressions />
<location endLine="27" endOffset="18" startLine="10" startOffset="4" />
</Target>
<Target id="@+id/tv_name" tag="binding_1" view="TextView">
<Expressions>
<Expression attribute="android:text" text="user.name">
<Location endLine="19" endOffset="38" startLine="19" startOffset="12" />
<TwoWay>false</TwoWay>
<ValueLocation endLine="19" endOffset="36" startLine="19" startOffset="28" />
</Expression>
</Expressions>
<location endLine="19" endOffset="41" startLine="15" startOffset="8" />
</Target>
<Target id="@+id/tv_age" tag="binding_2" view="TextView">
<Expressions>
<Expression attribute="android:text" text="user.age">
<Location endLine="25" endOffset="37" startLine="25" startOffset="12" />
<TwoWay>false</TwoWay>
<ValueLocation endLine="25" endOffset="35" startLine="25" startOffset="28" />
</Expression>
</Expressions>
<location endLine="25" endOffset="40" startLine="21" startOffset="8" />
</Target>
</Targets>
</Layout>
- 分析DataBindingUtil.setContentView(this,R.layout.activity_main)
//1.入口
DataBindingUtil.setContentView(this, initContentView())
//2.setContentView
public static <T extends ViewDataBinding> T setContentView(@NonNull Activity activity, int layoutId) {
return (T)setContentView(activity, layoutId, sDefaultComponent);
}
//3.setContentView
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(16908290);
return (T)bindToAddedViews(bindingComponent, contentView, 0, layoutId);
}
//4.bindToAddedViews
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);
//5.bind
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);
}
//5.bind
return bind(component, children, layoutId);
}
}
//6.1.sMapper是一个成员变量,指向DataBinderMapperImpl,DataBinderMapperImpl是apt自动生成的
private static DataBinderMapper sMapper = new DataBinderMapperImpl();
//5.bind
static <T extends ViewDataBinding> T bind(DataBindingComponent bindingComponent, View root,
int layoutId) {
//6.2.getDataBinder,会执行DataBinderMapper的getDataBinder,根据多态,执行DataBinderMapperImpl的getDataBinder函数
return (T) sMapper.getDataBinder(bindingComponent, root, layoutId);
}
//7.DataBinderMapperImpl的getDataBinder函数
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_ACTIVITYMAIN: {
if ("layout/activity_main_0".equals(tag)) {
//8.判断tag是否满足条件,执行new ActivityMainBindingImpl的操作
return new ActivityMainBindingImpl(component, view);
}
throw new IllegalArgumentException("The tag for activity_main is invalid. Received: " + tag);
}
}
}
return null;
}
- 查看 ActivityMainBindingImpl类的代码
public ActivityMainBindingImpl(@Nullable androidx.databinding.DataBindingComponent bindingComponent, @NonNull View root) {
//9.mapBindings函数(参数3的值由我们所写的布局来决定的,在ViewDataBinding类中)的调用 & 方法重载
this(bindingComponent, root, mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds));
}
private ActivityMainBindingImpl(androidx.databinding.DataBindingComponent bindingComponent, View root, Object[] bindings) {
//10.重载父类构造(即:ActivityMainBinding的构造)
super(bindingComponent, root, 1
, (android.widget.TextView) bindings[2]
, (android.widget.TextView) bindings[1]
);
this.mboundView0 = (android.widget.LinearLayout) bindings[0];
this.mboundView0.setTag(null);
this.tvAge.setTag(null);
this.tvName.setTag(null);
setRootTag(root);
// listeners
invalidateAll();
}
- ViewDataBinding类的mapBindings函数的作用:将我们写的xml布局中的View找出来存入到数组中,在重载ActivityMainBindingImpl构造时作为参数传递。
- 分析ActivityMainBinding的构造
protected ActivityMainBinding(Object _bindingComponent, View _root, int _localFieldCount,
TextView tvAge, TextView tvName) {
super(_bindingComponent, _root, _localFieldCount);
this.tvAge = tvAge;
this.tvName = tvName;
}
-
此时,我们就可以通过DataBindingUtil.setContentView(this,R.layout.activity_main)得到的对象,进行.tvAge或.tvName得到xml中所定义的View。
-
总结一下:DataBindingUtil.setContentView 做的事情,将Apt生成的对象new 出来 & 解析生成的XML文件 && 将XML中的View对象在ActivityMainBinding当中进行了存储。从而就需要findViewById了。
3.2.数据驱动UI的模型是如何设计的
-
这部分我们需要探讨的是,databinding是如何做到,model的改变后,view跟着改变;
-
源码看一轮之后,不建议按照源码的执行流程去分析了,我们得换个角度,如此,才能更快的把握好主体结构;
-
databinding实际上是使用观察者模式来实现的,底层还是View.settext方案来实现View的更新;既然是观察者模式,我们就需要分清楚被观察者和观察者,同时还需要知道如何建立联系的;
3.2.1.被观察者
- 我们在xml中通过variable设置的type对象就是被观察者,上方案例中的User是被观察者;
3.2.2.观察者
- 观察者:ViewDataBinding(抽象类,ActivityMainBinding是其子类,也是抽象类,而ActivityMainBinding的具体实现为ActivityMainBindingImpl),之所以认定其是观察者是因为javabean发生变化的时候,最终会触发其executeBindings方法,从而实现View的更新;
public class ActivityMainBindingImpl extends ActivityMainBinding {
//...
public void setUser(@Nullable com.jack.databinding.User User) {
updateRegistration(0, User);
//User被存储到ActivityMainBinding的成员变量mUser中
this.mUser = User;
synchronized(this) {
//在初始化阶段 mDirtyFlags被赋值了 mDirtyFlags = 2 ^ N,N由BR中的数量(总数量 - 1)决定的
mDirtyFlags |= 0x1L;
}
notifyPropertyChanged(BR.user);
super.requestRebind();
}
//...
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
java.lang.String userName = null;
java.lang.String userAge = null;
com.jack.databinding.User user = mUser;
if ((dirtyFlags & 0xfL) != 0) {
if ((dirtyFlags & 0xbL) != 0) {
if (user != null) {
// read user.name
userName = user.getName();
}
}
if ((dirtyFlags & 0xdL) != 0) {
if (user != null) {
// read user.age
userAge = user.getAge();
}
}
}
// batch finished
if ((dirtyFlags & 0xdL) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.tvAge, userAge);
}
if ((dirtyFlags & 0xbL) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.tvName, userName);
}
}
//...
}
- 观察者也清楚了,我们现在只需要弄明白被观察者跟观察者是如何建立关联,并且被观察者发生改变,被观察者是如何通知观察者做出相应,即可明白databiding的核心原理。
3.2.3.被观察者和观察者建立关联
- 这个建立关联的函数为setVariable,如下:
public boolean setVariable(int variableId, @Nullable Object variable) {
boolean variableSet = true;
if (BR.user == variableId) {
setUser((com.jack.databinding.User) variable);
}
else {
variableSet = false;
}
return variableSet;
}
- 我们就从setVariable开始逐步分析被观察者和观察者之间是如何建立关联的,这里的逻辑会有些绕,因为这里的建立关联跟传统的观察者模式不一样,传统的比较简单,但是这里用了大量的类和接口才真正的建立起关联。所以,这部分的逻辑会有些赋值,不过我们慢慢分析,还是会比较清晰的。我们就以setUser作为入口。
//ActivityMainBindingImpl类中
//1.步骤1
//---> setUser(@Nullable com.jack.databinding.User User)
//2.步骤2
//---> updateRegistration(0, User);
//3.步骤3
//--->ViewDataBinding类的updateRegistration(int localFieldId, Observable observable)
//4.步骤4 得开始贴详细代码了
//--->updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER)
//4.1.先看方法的第三个参数的代码
//CREATE_PROPERTY_LISTENER是ViewDataBinding类中静态的成员变量
//是一个匿名内部类的对象,此时create方法还未被调用
private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
@Override
public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
//这里可以看到WeakPropertyListener中持有viewDataBinding
return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
}
};
//4.2.updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER)
//localFieldId = 0,observable = personInfo
private boolean updateRegistration(int localFieldId, Object observable,
CreateWeakListener listenerCreator) {
//...
//mLocalFieldObservers是ViewDataBinding类的成员变量,是一个WeakListener数组
//mLocalFieldObservers的初始化时机是在ViewDataBinding的构造函数中
//WeakListener[] mLocalFieldObservers:存储BR中每一个属性 所对应的 监听器
WeakListener listener = mLocalFieldObservers[localFieldId];
//此时,listener为null
if (listener == null) {
//5.步骤5
registerTo(localFieldId, observable, listenerCreator);
return true;
}
if (listener.getTarget() == observable) {
return false;
}
//略...
}
//5.步骤5
protected void registerTo(int localFieldId, Object observable,
CreateWeakListener listenerCreator) {
//...
WeakListener listener = mLocalFieldObservers[localFieldId];
//此时还是为null,进入if
if (listener == null) {
//5.1.listenerCreator是4.1中的CREATE_PROPERTY_LISTENER
//此时,create方法调用了,WeakPropertyListener类被创建,listener指向WeakPropertyListener
listener = listenerCreator.create(this, localFieldId);
//mLocalFieldObservers[localFieldId] 被赋值
mLocalFieldObservers[localFieldId] = listener;
//当主动调用ViewDataBinding的setLifecycleOwner函数时,this.mLifecycleOwner就会有值。如在MainActivity中执行ActivityMainBinding.setLifecycleOwner(this),ViewDataBinding类中的静态内部类OnStartListener就能感知Avtivity的onStart生命周期变化事件(具体代码略);
if (this.mLifecycleOwner != null) {
//5.2.点进去查看,调用listener指向WeakPropertyListener的setLifecycleOwner函数,最终调用WeakPropertyListener(结合4.1中的CREATE_PROPERTY_LISTENER就可以知晓)的setLifecycleOwner(内部是一个空实现)
//listener.setLifecycleOwner对应的是WeakListener类的mObservable(指向的是WeakPropertyListener)成员变量执行setLifecycleOwner函数,即:将this.mLifecycleOwner传递到WeakPropertyListener中,但实际未做任何操作(方法是空实现)
listener.setLifecycleOwner(this.mLifecycleOwner);
}
//...
}
//6.步骤6
listener.setTarget(observable);
}
//6.步骤6
//执行WeakListener类setTarget方法
private static class WeakListener<T> extends WeakReference<ViewDataBinding> {
//...
public void setTarget(T object) {
unregister();
mTarget = object;
if (mTarget != null) {
//通过上面的CREATE_PROPERTY_LISTENER我们可以知道
//mObservable = WeakPropertyListener
//mTarget = User
//mObservable在这里是ObservableReference接口,故分析其具体实现类的方法
//7.步骤7:分析WeakPropertyListener的addListener
mObservable.addListener(mTarget);
}
}
//...
}
//7.步骤7
private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback
implements ObservableReference<Observable> {
final WeakListener<Observable> mListener;
//...
@Override
public void addListener(Observable target) {
//target = User
//调用父类Observable类(具体实现为)的addOnPropertyChangedCallback方法
//8.步骤8
target.addOnPropertyChangedCallback(this);
}
//...
}
//8.步骤8
public class BaseObservable implements Observable {
//...
@Override
public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
synchronized (this) {
if (mCallbacks == null) {
mCallbacks = new PropertyChangeRegistry();
}
}
//调用了mCallbacks(PropertyChangeRegistry)中的add方法。
//最终是将OnPropertyChangedCallback添加到一个List集合中(实际上是该接口的实现类-对应WeakPropertyListener)
//对于集合的添加,需要追踪到PropertyChangeRegistry的父类-CallbackRegistry-的add方法
//9.步骤9
mCallbacks.add(callback);
}
//...
}
//9.步骤9
//PropertyChangeRegistry父类-CallbackRegistry类
private List<C> mCallbacks = new ArrayList<C>();
public synchronized void add(C callback) {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
int index = mCallbacks.lastIndexOf(callback);
if (index < 0 || isRemoved(index)) {
mCallbacks.add(callback);
}
}
- 总结一下,步骤1-步骤9所作的事情,观察者ViewDataBinding中有个数组,每一个被观察者对应该数组中一个WeakListener类,WeakListener给被观察者做了一件事情,给被添加了一个接口,该接口最终是被存储到CallbackRegistry类的集合中;
- 建立关系到这里已经完成,但是我们还看不出是如何触发,触发时机上跟传统的观察者模式一样,触发的api是定义在了被观察者中。下面,我们来分析通知观察者的api。
3.2.4.BaseObservable类
- 通知观察者的api为BaseObservable的notifyPropertyChanged(fieldId)
- 调用User的setName,会触发notifyPropertyChanged(BR.name)(其它也类似,即User发生变化);
//10.步骤10
public void notifyPropertyChanged(int fieldId) {
synchronized (this) {
if (mCallbacks == null) {
return;
}
}
//11.步骤11
mCallbacks.notifyCallbacks(this, fieldId, null);
}
//11.步骤11
public synchronized void notifyCallbacks(T sender, int arg, A arg2) {
mNotificationLevel++;
//12.步骤12
notifyRecurse(sender, arg, arg2);
mNotificationLevel--;
//...
}
//12.步骤12
private void notifyRecurse(T sender, int arg, A arg2) {
//13.步骤13
notifyCallbacks(sender, arg, arg2, startCallbackIndex, callbackCount, 0);
}
//13.步骤13
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) {
//步骤14
//mNotifier的赋值为PropertyChangeRegistry类中的NOTIFIER_CALLBACK
//这里实际上就是遍历CallbackRegistry类中的mCallbacks的所有对象(实际存储的是WeakPropertyListener),将其作为下方函数的第一个参数进行传递
mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg, arg2);
}
bitMask <<= 1;
}
}
//14.步骤14
public abstract static class NotifierCallback<C, T, A> {
public abstract void onNotifyCallback(C callback, T sender, int arg, A arg2);
}
public class PropertyChangeRegistry extends CallbackRegistry<OnPropertyChangedCallback, Observable, Void> {
private static final NotifierCallback<OnPropertyChangedCallback, Observable, Void> NOTIFIER_CALLBACK = new NotifierCallback<OnPropertyChangedCallback, Observable, Void>() {
//实际调用的位置,PropertyChangeRegistry类中匿名内部类NOTIFIER_CALLBACK对于的onNotifyCallback回调
public void onNotifyCallback(OnPropertyChangedCallback callback, Observable sender, int arg, Void notUsed) {
//调用Observable类中的OnPropertyChangedCallback的实现类的onPropertyChanged方法
//15.步骤15
callback.onPropertyChanged(sender, arg);
}
};
public PropertyChangeRegistry() {
super(NOTIFIER_CALLBACK);
}
public void notifyChange(@NonNull Observable observable, int propertyId) {
this.notifyCallbacks(observable, propertyId, (Object)null);
}
}
//15.步骤15:根据多态,会执行WeakPropertyListener的onPropertyChanged
abstract class OnPropertyChangedCallback {
public abstract void onPropertyChanged(Observable sender, int propertyId);
}
private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback
implements ObservableReference<Observable> {
//...
//实际调用
//15.步骤15
@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?
}
//调用handleFieldChange:处理字段修改的过程
//16.步骤16
binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
}
}
- 现在可以把步骤1-步骤16联系起来,也就是被观察者和观察者建立了关联,同时model改变后,被观察者发送通知给观察者,最终是回调了ViewDataBinding的handleFieldChange方法,我们只要分析出该方法最终的调用,看具体的操作即可;
3.2.5.ViewDataBinding的handleFieldChange方法
//17.步骤17
private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
//...
//onFieldChange的具体实现在ActivityMainBindingImpl中
//内部最终计算是二进制的&和|操作,若被观察者未发生变化,则不会进入if(即属性不需要更新)
boolean result = onFieldChange(mLocalFieldId, object, fieldId);
if (result) {
//分析requestRebind
//18.步骤18
requestRebind();
}
}
//18.步骤18
//条件判断略掉(避免过于深入细节)
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;
}
//API16及以上 USE_CHOREOGRAPHER 为 true
if (USE_CHOREOGRAPHER) {
//19.步骤19,API16 及以上 会嵌入到编舞者的执行过程中,最终会触发doFrame回调
//会执行mRebindRunnable的run方法,即最终跟else语句执行的一样
//mFrameCallback的创建在ViewDataBinding的构造函数中
mChoreographer.postFrameCallback(mFrameCallback);
} else {
//会回调mRebindRunnable的run方法
//19.步骤19
mUIThreadHandler.post(mRebindRunnable);
}
}
}
//19.步骤19
this.mRebindRunnable = new Runnable() {
public void run() {
synchronized(this) {
ViewDataBinding.this.mPendingRebind = false;
}
ViewDataBinding.processReferenceQueue();
if (VERSION.SDK_INT >= 19 && !ViewDataBinding.this.mRoot.isAttachedToWindow()) {
ViewDataBinding.this.mRoot.removeOnAttachStateChangeListener(ViewDataBinding.ROOT_REATTACHED_LISTENER);
ViewDataBinding.this.mRoot.addOnAttachStateChangeListener(ViewDataBinding.ROOT_REATTACHED_LISTENER);
} else {
//20.步骤20
ViewDataBinding.this.executePendingBindings();
}
}
};
//20.步骤20
public void executePendingBindings() {
if (mContainingBinding == null) {
//会调用executeBindingsInternal
//21.步骤21
executeBindingsInternal();
} else {
mContainingBinding.executePendingBindings();
}
}
//21.步骤21
private void executeBindingsInternal() {
//...
if (!mRebindHalted) {
//抽象方法,具体实现在在ActivityMainBindingImpl中查看
//22.步骤22
executeBindings();
//...
}
//...
}
//22.步骤22
//ActivityMainBindingImpl类
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
java.lang.String userName = null;
java.lang.String userAge = null;
com.jack.databinding.User user = mUser;
if ((dirtyFlags & 0xfL) != 0) {
if ((dirtyFlags & 0xbL) != 0) {
if (user != null) {
// read user.name
userName = user.getName();
}
}
if ((dirtyFlags & 0xdL) != 0) {
if (user != null) {
// read user.age
userAge = user.getAge();
}
}
}
// batch finished
if ((dirtyFlags & 0xdL) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.tvAge, userAge);
}
if ((dirtyFlags & 0xbL) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.tvName, userName);
}
}
//TextViewBindingAdapter.setText最终还是View.setText
3.3.View改变是如何驱动Model变化的
//executeBindings函数
if ((dirtyFlags & 0x8L) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.tvAge, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, tvAgeandroidTextAttrChanged);
androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.tvName, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, tvNameandroidTextAttrChanged);
}
//匿名内部类
private androidx.databinding.InverseBindingListener tvAgeandroidTextAttrChanged = new androidx.databinding.InverseBindingListener() {
@Override
public void onChange() {
// Inverse of user.age
// is user.setAge((java.lang.String) callbackArg_0)
java.lang.String callbackArg_0 = androidx.databinding.adapters.TextViewBindingAdapter.getTextString(tvAge);
// localize variables for thread safety
// user != null
boolean userJavaLangObjectNull = false;
// user.age
java.lang.String userAge = null;
// user
com.jack.databinding.User user = mUser;
userJavaLangObjectNull = (user) != (null);
if (userJavaLangObjectNull) {
user.setAge(((java.lang.String) (callbackArg_0)));
}
}
};
- 总结:通过设置监听器的方式来实现的;
四.总结
- Databinding数据驱动UI的更新的核心我们可以根据下图来做一个总结。如图:
- 被观察者有一个管家PropertyChangeRegistry mCallbacks,该管家对注册的监听进行管理,监听是间接的持有ViewDatabinding的引用;
- 当被观察者发生改变,并不是像传递的观察者模式一样,直接持有观察者的引用去进行通知,而是 通知管家,让管家将注册的监听进行全部遍历, 而监听因为间接持有ViewDatabinding的引用,从而可以对观察者进行通知来实现UI的更新。
- 到此,我们对Databinding的原理和源码分析有了一个很不错的了解 && Databinding在多对多关系的处理上,如:通过WeakListener同时持有被观察者和观察者,通过注册的方式将WeakPropertyListener存储到了CallbackRegistry 的集合中,WeakPropertyListener持有WeakListener引用等方式。有助于对设计类似架构的学习。
评论区