织梦网站tel标签,找手工活做注册网站,成都网站建设模版,企业形象包装设计慢品人间烟火色#xff0c;闲观万事岁月长 一#xff0c;基本使用
关于databinding的基本使用请看之前的文章
Android--Jetpack--Databinding详解-CSDN博客 二#xff0c;xml布局解析
分析源码呢#xff0c;主要就是从两方面入手#xff0c;一个是使用#xff0c;一个…慢品人间烟火色闲观万事岁月长 一基本使用
关于databinding的基本使用请看之前的文章
Android--Jetpack--Databinding详解-CSDN博客 二xml布局解析
分析源码呢主要就是从两方面入手一个是使用一个是APT生成的代码。
我们看一下上一篇文章我们的布局xml文件
?xml version1.0 encodingutf-8?
layout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsdata classMyDataBingimport typecom.yuanzhen.lifecycledemo.databing.YuanZhen/variablenameyuanzhentypeYuanZhen//dataRelativeLayoutandroid:layout_widthmatch_parentandroid:layout_heightmatch_parenttools:context.MainActivityTextViewandroid:idid/txt_nameandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:text{yuanzhen.name}android:textSize40spapp:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparent /TextViewandroid:idid/txt_ageandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:textSize40spandroid:text{String.valueOf(yuanzhen.age)}app:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparentandroid:layout_belowid/txt_name/EditTextandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_belowid/txt_ageandroid:textSize40spandroid:text{yuanzhen.name}//RelativeLayout
/layout
然后我们看一下APT生成的代码 打开之后格式化一下看看代码
?xml version1.0 encodingutf-8 standaloneyes?
Layout bindingClassMyDataBing directorylayoutfilePathapp\src\main\res\layout\activity_main.xml isBindingDatatrueisMergefalse layoutactivity_main modulePackagecom.yuanzhen.lifecycledemorootNodeTypeandroid.widget.RelativeLayoutClassNameLocation endLine5 endOffset26 startLine5 startOffset17 /Variables nameyuanzhen declaredtrue typeYuanZhenlocation endLine9 endOffset28 startLine7 startOffset8 //VariablesImports nameYuanZhen typecom.yuanzhen.lifecycledemo.databing.YuanZhenlocation endLine6 endOffset68 startLine6 startOffset8 //ImportsTargetsTarget taglayout/activity_main_0 viewRelativeLayoutExpressions /location endLine48 endOffset20 startLine12 startOffset4 //TargetTarget idid/txt_name tagbinding_1 viewTextViewExpressionsExpression attributeandroid:text textyuanzhen.nameLocation endLine21 endOffset42 startLine21 startOffset12 /TwoWayfalse/TwoWayValueLocation endLine21 endOffset40 startLine21 startOffset28 //Expression/Expressionslocation endLine26 endOffset55 startLine17 startOffset8 //TargetTarget idid/txt_age tagbinding_2 viewTextViewExpressionsExpression attributeandroid:text textString.valueOf(yuanzhen.age)Location endLine33 endOffset57 startLine33 startOffset12 /TwoWayfalse/TwoWayValueLocation endLine33 endOffset55 startLine33 startOffset28 //Expression/Expressionslocation endLine38 endOffset49 startLine28 startOffset8 //TargetTarget tagbinding_3 viewEditTextExpressionsExpression attributeandroid:text textyuanzhen.nameLocation endLine44 endOffset43 startLine44 startOffset12 /TwoWaytrue/TwoWayValueLocation endLine44 endOffset41 startLine44 startOffset29 //Expression/Expressionslocation endLine44 endOffset45 startLine39 startOffset8 //Target/Targets
/Layout
我们发现每个view都包装了一个Targets标签对应了一个tag。
比如RelativeLayout对应的是layout/activity_main_0
然后看看我们的textview
Target idid/txt_name tagbinding_1 viewTextViewExpressionsExpression attributeandroid:text textyuanzhen.nameLocation endLine21 endOffset42 startLine21 startOffset12 /TwoWayfalse/TwoWayValueLocation endLine21 endOffset40 startLine21 startOffset28 //Expression/Expressionslocation endLine26 endOffset55 startLine17 startOffset8 /
/Target 通过text将yuanzhen.name赋值给了textview
然后在打开另一个APT生成的文件 看看它的代码
?xml version1.0 encodingutf-8?RelativeLayoutandroid:layout_widthmatch_parentandroid:layout_heightmatch_parenttools:context.MainActivity android:taglayout/activity_main_0 xmlns:androidhttp://schemas.android.com/apk/res/android xmlns:apphttp://schemas.android.com/apk/res-auto xmlns:toolshttp://schemas.android.com/toolsTextViewandroid:idid/txt_nameandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:tagbinding_1 android:textSize40spapp:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparent /TextViewandroid:idid/txt_ageandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:textSize40spandroid:tagbinding_2 app:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparentandroid:layout_belowid/txt_name/EditTextandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_belowid/txt_ageandroid:textSize40spandroid:tagbinding_3 //RelativeLayout
上面空了一大块把布局文件的layout去掉了其余的和我们的布局文件一样除此之外它给每个view都增加了一个tag这个tag与上面的tag一一对应这就是布局的解析。 三xml代码解析
首先我们看一下上一章我们的使用代码
public class MainActivity extends AppCompatActivity {private MyDataBing dataBinding;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);dataBinding DataBindingUtil.setContentView(this, R.layout.activity_main);YuanZhen yuanZhen new YuanZhen(袁震,18);dataBinding.setYuanzhen(yuanZhen);new Thread(new Runnable() {Overridepublic void run() {for (int i 0; i 10; i) {try {Thread.sleep(1000);yuanZhen.setName(yuanZhen.getName()i);yuanZhen.setAge(18i);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();}}
首先我们看一下dataBinding DataBindingUtil.setContentView(this, R.layout.activity_main)这句代码的实现,它会走到DataBindingUtil的setContentView():
public static T extends ViewDataBinding T setContentView(NonNull Activity activity,int layoutId) {return setContentView(activity, layoutId, sDefaultComponent);
}
继续往里面看
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);
}
前三行代码我们应该都能看懂
获取到了conetntView,并传入了方法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);}
}
该方法会调用bind(component, children, layoutId)方法
static T extends ViewDataBinding T bind(DataBindingComponent bindingComponent, View root,int layoutId) {return (T) sMapper.getDataBinder(bindingComponent, root, layoutId);
}
然后会调用 sMapper.getDataBinder(bindingComponent, root, layoutId)
public abstract class DataBinderMapper {public abstract ViewDataBinding getDataBinder(DataBindingComponent bindingComponent, View view,int layoutId);public abstract ViewDataBinding getDataBinder(DataBindingComponent bindingComponent,View[] view, int layoutId);public abstract int getLayoutId(String tag);public abstract String convertBrIdToString(int id);NonNullpublic ListDataBinderMapper collectDependencies() {// default implementation for backwards compatibility.return Collections.emptyList();}
}
然后查看getDataBinder的引用会找到APT生成的DataBinderMapperImpl类的getDataBinder方法
public class DataBinderMapperImpl extends DataBinderMapper {。。。Overridepublic 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)) {return new MyDataBingImpl(component, view);}throw new IllegalArgumentException(The tag for activity_main is invalid. Received: tag);}}}return null;
}
。。。}
这里比较关键的代码是如果我们传过来的tag是layout/activity_main_0就是前面生成的xml里面的根节点的tag那么就创建我们自定义命名的MyDataBingImpl。
然后我们查看MyDataBingImpl的构造函数
public MyDataBingImpl(Nullable androidx.databinding.DataBindingComponent bindingComponent, NonNull View root) {this(bindingComponent, root, mapBindings(bindingComponent, root, 4, sIncludes, sViewsWithIds));
}
会发现这里有个44的意思就是xml文件里面的4个view节点。
继续往下看mapBindings源码
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;
} 创建了一个大小为4的对象数组然后调用mapBindings
private static void mapBindings(DataBindingComponent bindingComponent, View view,Object[] bindings, IncludedLayouts includes, SparseIntArray viewsWithIds,boolean isRoot) {final int indexInIncludes;final ViewDataBinding existingBinding getBinding(view);if (existingBinding ! null) {return;}Object objTag view.getTag();final String tag (objTag instanceof String) ? (String) objTag : null;boolean isBound false;if (isRoot tag ! null tag.startsWith(layout)) {final int underscoreIndex tag.lastIndexOf(_);if (underscoreIndex 0 isNumeric(tag, underscoreIndex 1)) {final int index parseTagInt(tag, underscoreIndex 1);if (bindings[index] null) {bindings[index] view;}indexInIncludes includes null ? -1 : index;isBound true;} else {indexInIncludes -1;}} else if (tag ! null tag.startsWith(BINDING_TAG_PREFIX)) {int tagIndex parseTagInt(tag, BINDING_NUMBER_START);if (bindings[tagIndex] null) {bindings[tagIndex] view;}isBound true;indexInIncludes includes null ? -1 : tagIndex;} else {// Not a bound viewindexInIncludes -1;}if (!isBound) {final int id view.getId();if (id 0) {int index;if (viewsWithIds ! null (index viewsWithIds.get(id, -1)) 0 bindings[index] null) {bindings[index] view;}}}if (view instanceof ViewGroup) {final ViewGroup viewGroup (ViewGroup) view;final int count viewGroup.getChildCount();int minInclude 0;for (int i 0; i count; i) {final View child viewGroup.getChildAt(i);boolean isInclude false;if (indexInIncludes 0 child.getTag() instanceof String) {String childTag (String) child.getTag();if (childTag.endsWith(_0) childTag.startsWith(layout) childTag.indexOf(/) 0) {// This *could* be an include. Test against the expected includes.int includeIndex findIncludeIndex(childTag, minInclude,includes, indexInIncludes);if (includeIndex 0) {isInclude true;minInclude includeIndex 1;final int index includes.indexes[indexInIncludes][includeIndex];final int layoutId includes.layoutIds[indexInIncludes][includeIndex];int lastMatchingIndex findLastMatching(viewGroup, i);if (lastMatchingIndex i) {bindings[index] DataBindingUtil.bind(bindingComponent, child,layoutId);} else {final int includeCount lastMatchingIndex - i 1;final View[] included new View[includeCount];for (int j 0; j includeCount; j) {included[j] viewGroup.getChildAt(i j);}bindings[index] DataBindingUtil.bind(bindingComponent, included,layoutId);i includeCount - 1;}}}}if (!isInclude) {mapBindings(bindingComponent, child, bindings, includes, viewsWithIds, false);}}}
}
这段源码主要是通过tag解析出view放到数组里面。
这样我们在使用的时候就能拿到xml里面的view了
这样xml的代码解析就完成了。
四核心原理
databinding的核心逻辑就是更新数据的同时自动更新UI。那么我们可以判断出它的整体实际上肯定是一个观察者模式。首先被观察者肯定是数据类就是我们的YuanZhen这个类
public class YuanZhen extends BaseObservable {public YuanZhen(String name, int age) {this.name name;this.age age;}private String name;private int age;public void setName(String name) {this.name name;notifyPropertyChanged(BR.name);}public void setAge(int age) {this.age age;notifyPropertyChanged(BR.age);}Bindablepublic String getName() {return name;}Bindablepublic int getAge() {return age;}
}
它继承了BaseObservable并且在数据发生变化的时候调用了notify方法通知观察者去更新UI。 所以观察者肯定是更新ui的类就是我们APT生成的MyDataBingImpl这个类。
中间肯定会有注册和反注册观察者的逻辑。下面我们还是先从使用入手分析:
我们来看下这句代码dataBinding.setYuanzhen(yuanZhen) 它是初始化的代码直接点击是找不到的它是在APT生成的MyDataBingImpl类里面
SuppressWarnings(unchecked)
public class MyDataBingImpl extends MyDataBing {。。。。public void setYuanzhen(Nullable com.yuanzhen.lifecycledemo.databing.YuanZhen Yuanzhen) {updateRegistration(0, Yuanzhen);this.mYuanzhen Yuanzhen;synchronized(this) {mDirtyFlags | 0x1L;}notifyPropertyChanged(BR.yuanzhen);super.requestRebind();}}
先来看updateRegistration(0, Yuanzhen)
protected boolean updateRegistration(int localFieldId, Observable observable) {return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);
}
先看看第三个参数 CREATE_PROPERTY_LISTENER从名字可以看出它是创建Property监听器的看看它的源码
private static final CreateWeakListener CREATE_PROPERTY_LISTENER new CreateWeakListener() {Overridepublic WeakListener create(ViewDataBinding viewDataBinding,int localFieldId,ReferenceQueueViewDataBinding referenceQueue) {return new WeakPropertyListener(viewDataBinding, localFieldId, referenceQueue).getListener();}
};
果然是创建了一个WeakPropertyListener看看它的源码
private static class WeakPropertyListener extends Observable.OnPropertyChangedCallbackimplements ObservableReferenceObservable {final WeakListenerObservable mListener;public WeakPropertyListener(ViewDataBinding binder,int localFieldId,ReferenceQueueViewDataBinding referenceQueue) {mListener new WeakListenerObservable(binder, localFieldId, this, referenceQueue);}Overridepublic WeakListenerObservable getListener() {return mListener;}Overridepublic void addListener(Observable target) {target.addOnPropertyChangedCallback(this);}Overridepublic void removeListener(Observable target) {target.removeOnPropertyChangedCallback(this);}Overridepublic void setLifecycleOwner(LifecycleOwner lifecycleOwner) {}Overridepublic 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);}
}
从源码大致可以看出这个监听器内部创建了WeakListener 并且将WeakListenter和 ViewDataBindinglocalFieldId进行绑定并在调用onPropertyChanged方法时调用ViewDataBinding的handleFieldChange方法并将WeakListenter的mLocalFieldId传给后者。
然后看下WeakListener 的源码
RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
class WeakListenerT extends WeakReferenceViewDataBinding {private final ObservableReferenceT mObservable;protected final int mLocalFieldId;private T mTarget;public WeakListener(ViewDataBinding binder,int localFieldId,ObservableReferenceT observable,ReferenceQueueViewDataBinding referenceQueue) {super(binder, referenceQueue);mLocalFieldId localFieldId;mObservable observable;}public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {mObservable.setLifecycleOwner(lifecycleOwner);}public void setTarget(T object) {unregister();mTarget object;if (mTarget ! null) {mObservable.addListener(mTarget);}}public boolean unregister() {boolean unregistered false;if (mTarget ! null) {mObservable.removeListener(mTarget);unregistered true;}mTarget null;return unregistered;}public T getTarget() {return mTarget;}Nullableprotected ViewDataBinding getBinder() {ViewDataBinding binder get();if (binder null) {unregister(); // The binder is dead}return binder;}
} 在WeakListener 里面主要是将ViewDataBinding和localFieldId进行了绑定
然后我们再继续看updateRegistration的源码
RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
protected 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;}if (listener.getTarget() observable) {return false;//nothing to do, same object}unregisterFrom(localFieldId);registerTo(localFieldId, observable, listenerCreator);return true;
}
mLocalFieldObservers[localFieldId]看看它是什么时候创建的
private WeakListener[] mLocalFieldObservers;
protected ViewDataBinding(DataBindingComponent bindingComponent, View root, int localFieldCount) {mBindingComponent bindingComponent;mLocalFieldObservers new WeakListener[localFieldCount];this.mRoot root;if (Looper.myLooper() null) {throw new IllegalStateException(DataBinding must be created in views UI Thread);}if (USE_CHOREOGRAPHER) {mChoreographer Choreographer.getInstance();mFrameCallback new Choreographer.FrameCallback() {Overridepublic void doFrame(long frameTimeNanos) {mRebindRunnable.run();}};} else {mFrameCallback null;mUIThreadHandler new Handler(Looper.myLooper());}
}
原来是在我们上面讲的xml代码解析里面初始化ViewDataBinding的时候创建的
public MyDataBingImpl(Nullable androidx.databinding.DataBindingComponent bindingComponent, NonNull View root) {this(bindingComponent, root, mapBindings(bindingComponent, root, 4, sIncludes, sViewsWithIds));
}
并且数组的大小是4。这个4是怎么来的呢?
继续返回MyDataBingImpl的setYuanzhen方法往下看
notifyPropertyChanged(BR.yuanzhen);
看一下BR这个类也是APT生成的
public class BR {public static final int _all 0;public static final int age 1;public static final int name 2;public static final int yuanzhen 3;
}
主要就是将属性用数字定义了。数组的大小 就是这个类的属性的数量。
再返回头来看updateRegistration如果WeakLister不存在就走registerTo(localFieldId, observable, listenerCreator);方法
protected void registerTo(int localFieldId, Object observable,CreateWeakListener listenerCreator) {if (observable null) {return;}WeakListener listener mLocalFieldObservers[localFieldId];if (listener null) {listener listenerCreator.create(this, localFieldId, sReferenceQueue);mLocalFieldObservers[localFieldId] listener;if (mLifecycleOwner ! null) {listener.setLifecycleOwner(mLifecycleOwner);}}listener.setTarget(observable);
}
这个方法主要是通过上面创建的CreateWeakListener来创建WeakListener并将WeakListener放入mLocalFieldObservers数组中它对应的位置。
看完了初始化绑定关系再来看看被观察者BaseObservable
public class BaseObservable implements Observable {private transient PropertyChangeRegistry mCallbacks;public BaseObservable() {}Overridepublic void addOnPropertyChangedCallback(NonNull OnPropertyChangedCallback callback) {synchronized (this) {if (mCallbacks null) {mCallbacks new PropertyChangeRegistry();}}mCallbacks.add(callback);}Overridepublic void removeOnPropertyChangedCallback(NonNull OnPropertyChangedCallback callback) {synchronized (this) {if (mCallbacks null) {return;}}mCallbacks.remove(callback);}/*** Notifies listeners that all properties of this instance have changed.*/public void notifyChange() {synchronized (this) {if (mCallbacks null) {return;}}mCallbacks.notifyCallbacks(this, 0, null);}/*** 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* codeBR/code to be used as codefieldId/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);}
}
首先看mCallbacks的源码
public class PropertyChangeRegistry extendsCallbackRegistryObservable.OnPropertyChangedCallback, Observable, Void {private static final CallbackRegistry.NotifierCallbackObservable.OnPropertyChangedCallback, Observable, Void NOTIFIER_CALLBACK new CallbackRegistry.NotifierCallbackObservable.OnPropertyChangedCallback, Observable, Void() {Overridepublic 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);}
}
可以看出它主要是用来通知观察者更新消息的。
我们调用notifyPropertyChanged就会调用PropertyChangeRegistry的notifyChange方法。
然后依次往下调用
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;}}
}
之后notifyRecurse
private void notifyRecurse(T sender, int arg, A arg2) {final int callbackCount mCallbacks.size();final int remainderIndex mRemainderRemoved null ? -1 : mRemainderRemoved.length - 1;// Now weve got all callbakcs that have no mRemainderRemoved value, so notify the// others.notifyRemainder(sender, arg, arg2, remainderIndex);// notifyRemainder notifies all at maxIndex, so wed 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 setnotifyCallbacks(sender, arg, arg2, startCallbackIndex, callbackCount, 0);
}
然后
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;}
}
然后看看NotifierCallback
public abstract static class NotifierCallbackC, T, A {/*** Called by CallbackRegistry during* {link CallbackRegistry#notifyCallbacks(Object, int, Object)}} to notify the callback.** param callback The callback to notify.* param sender The opaque sender object.* param arg The opaque notification parameter.* param arg2 An opaque argument passed in* {link CallbackRegistry#notifyCallbacks}* see CallbackRegistry#CallbackRegistry(CallbackRegistry.NotifierCallback)*/public abstract void onNotifyCallback(C callback, T sender, int arg, A arg2);
}
之后又回到了PropertyChangeRegistry的回调里面 public class PropertyChangeRegistry extends CallbackRegistryObservable.OnPropertyChangedCallback, Observable, Void {private static final CallbackRegistry.NotifierCallbackObservable.OnPropertyChangedCallback, Observable, Void NOTIFIER_CALLBACK new CallbackRegistry.NotifierCallbackObservable.OnPropertyChangedCallback, Observable, Void() {public void onNotifyCallback(Observable.OnPropertyChangedCallback callback, Observable sender, int arg, Void notUsed) {callback.onPropertyChanged(sender, arg);}};public PropertyChangeRegistry() {super(NOTIFIER_CALLBACK);}public void notifyChange(NonNull Observable observable, int propertyId) {this.notifyCallbacks(observable, propertyId, (Object)null);}
} 然后继续往下走onPropertyChanged
public interface Observable {/*** Adds a callback to listen for changes to the Observable.* param callback The callback to start listening.*/void addOnPropertyChangedCallback(OnPropertyChangedCallback callback);/*** Removes a callback from those listening for changes.* param callback The callback that should stop listening.*/void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback);/*** The callback that is called by Observable when an observable property has changed.*/abstract class OnPropertyChangedCallback {/*** Called by an Observable whenever an observable property changes.* param sender The Observable that is changing.* param propertyId The BR identifier of the property that has changed. The getter* for this property should be annotated with {link Bindable}.*/public abstract void onPropertyChanged(Observable sender, int propertyId);}
} 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);
}
继续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);}}
}
然后看看mRebindRunnable里面
private final Runnable mRebindRunnable new Runnable() {Overridepublic void run() {synchronized (this) {mPendingRebind false;}processReferenceQueue();if (VERSION.SDK_INT VERSION_CODES.KITKAT) {// Nested so that we dont get a lint warning in IntelliJif (!mRoot.isAttachedToWindow()) {// Dont execute the pending bindings until the View// is attached again.mRoot.removeOnAttachStateChangeListener(ROOT_REATTACHED_LISTENER);mRoot.addOnAttachStateChangeListener(ROOT_REATTACHED_LISTENER);return;}}executePendingBindings();}
};
之后executePendingBindings
private void executeBindingsInternal() {if (mIsExecutingPendingBindings) {requestRebind();return;}if (!hasPendingBindings()) {return;}mIsExecutingPendingBindings true;mRebindHalted false;if (mRebindCallbacks ! null) {mRebindCallbacks.notifyCallbacks(this, REBIND, null);// The onRebindListeners will change mPendingHaltedif (mRebindHalted) {mRebindCallbacks.notifyCallbacks(this, HALTED, null);}}if (!mRebindHalted) {executeBindings();if (mRebindCallbacks ! null) {mRebindCallbacks.notifyCallbacks(this, REBOUND, null);}}mIsExecutingPendingBindings false;
}
看看executeBindings()
protected abstract void executeBindings();
然后在MyDataBingImpl里面找到它的实现 Overrideprotected void executeBindings() {long dirtyFlags 0;synchronized(this) {dirtyFlags mDirtyFlags;mDirtyFlags 0;}java.lang.String yuanzhenName null;com.yuanzhen.lifecycledemo.databing.YuanZhen yuanzhen mYuanzhen;int yuanzhenAge 0;java.lang.String stringValueOfYuanzhenAge null;if ((dirtyFlags 0xfL) ! 0) {if ((dirtyFlags 0xbL) ! 0) {if (yuanzhen ! null) {// read yuanzhen.nameyuanzhenName yuanzhen.getName();}}if ((dirtyFlags 0xdL) ! 0) {if (yuanzhen ! null) {// read yuanzhen.ageyuanzhenAge yuanzhen.getAge();}// read String.valueOf(yuanzhen.age)stringValueOfYuanzhenAge java.lang.String.valueOf(yuanzhenAge);}}// batch finishedif ((dirtyFlags 0xbL) ! 0) {// api target 1androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView3, yuanzhenName);androidx.databinding.adapters.TextViewBindingAdapter.setText(this.txtName, yuanzhenName);}if ((dirtyFlags 0x8L) ! 0) {// api target 1androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.mboundView3, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, mboundView3androidTextAttrChanged);}if ((dirtyFlags 0xdL) ! 0) {// api target 1androidx.databinding.adapters.TextViewBindingAdapter.setText(this.txtAge, stringValueOfYuanzhenAge);}}
看到上面的最终数据的改变也是通过调用setText等方法来实现的。