首先找到app的build.gradle:
- android {
- compileSdk 32
-
- defaultConfig {
- applicationId "com.example.myapplication"
- minSdk 24
- targetSdk 32
- versionCode 1
- versionName "1.0"
-
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- kotlinOptions {
- jvmTarget = '1.8'
- }
-
- //添加下面的配置
- dataBinding {
- enabled = true
- }
-
- }
然后进xml文件,将我们的xml转成databinding布局:
- "1.0" encoding="utf-8"?>
- <layout 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">
-
- <data>
-
- data>
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".MainActivity">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Hello World!"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintRight_toRightOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
-
- androidx.constraintlayout.widget.ConstraintLayout>
- layout>
关于IDE自动转databinding布局的说明:将鼠标停在最外层的constraintLayout的布局的里面的空闲位置,然后同时按option+enter(Mac),就会出现convert to data binding layout提示。
我们先写一个bean:
- package com.example.myapplication
-
- import androidx.annotation.Keep
-
- @Keep
- data class User(
- var userName: String,
- var passWord: String
- )
然后布局这样写:
- "1.0" encoding="utf-8"?>
- <layout 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">
-
- <data>
-
- <variable
- name="user"
- type="com.example.myapplication.User" />
-
- data>
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".MainActivity">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@{user.userName}"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintRight_toRightOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
-
- androidx.constraintlayout.widget.ConstraintLayout>
- layout>
name是名称,可以随便写,一般最好与bean一致,type就是具体定义的类型。@{user.***}实现了数据的引用。
MainActivity使用:
- package com.example.myapplication
-
- import androidx.appcompat.app.AppCompatActivity
- import android.os.Bundle
- import androidx.databinding.DataBindingUtil
- import com.example.myapplication.databinding.ActivityMainBinding
-
- class MainActivity : AppCompatActivity() {
-
- var activityMainBinding: ActivityMainBinding? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- //setContentView(R.layout.activity_main)
- activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
- val user = User("lzy", "123456")
- activityMainBinding?.user = user
- }
- }
注意,原有的设置布局的方式要换成通过DataBindingUtil的方式。
运行一把:

这样就完成了最基本的databinding的使用了。那有些同学可能会说,这样很麻烦呀,使用databinding的优势在哪里呢?我们接着看:
- package com.example.myapplication
-
- import androidx.appcompat.app.AppCompatActivity
- import android.os.Bundle
- import androidx.databinding.DataBindingUtil
- import com.example.myapplication.databinding.ActivityMainBinding
- import java.lang.Thread.sleep
-
- class MainActivity : AppCompatActivity() {
-
- var activityMainBinding: ActivityMainBinding? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- //setContentView(R.layout.activity_main)
- activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
- val user = User("lzy", "123456")
- activityMainBinding?.user = user
-
- Thread {
- for (i in 0 until 100) {
- sleep(1000)
- user.userName = "lzy".plus(i)
- activityMainBinding?.user = user
- }
- }.start()
- }
- }
我们看到的效果是这样的:

每一秒钟,UI就会自动变化,我们只有一个TextView还不是很明显,如果我们有很多View,当数据类发生变化的时候,会自动驱动UI变化,这样会使代码更加简洁,我们就不需要每一个View都去设置数据了。
更进一步,我们还可以定义这样一个Bean类:
- package com.example.myapplication;
-
- import androidx.annotation.Keep;
- import androidx.databinding.BaseObservable;
- import androidx.databinding.Bindable;
-
- @Keep
- public class User2 extends BaseObservable {
-
- private String userName;
- private String passWord;
-
- @Bindable
- public String getUserName() {
- return userName;
- }
-
- public void setUserName(String userName) {
- this.userName = userName;
- notifyPropertyChanged(BR.userName);
- }
-
- @Bindable
- public String getPassWord() {
- return passWord;
- }
-
- public void setPassWord(String passWord) {
- this.passWord = passWord;
- notifyPropertyChanged(BR.passWord);
- }
-
- }
使用:
- package com.example.myapplication
-
- import androidx.appcompat.app.AppCompatActivity
- import android.os.Bundle
- import androidx.databinding.DataBindingUtil
- import com.example.myapplication.databinding.ActivityMainBinding
- import java.lang.Thread.sleep
-
- class MainActivity : AppCompatActivity() {
-
- private var activityMainBinding: ActivityMainBinding? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
- //val user = User("lzy", "123456")
- val user = User2()
- user.userName = "lzy2"
- user.passWord = "123456789"
- activityMainBinding?.user = user
-
- Thread {
- for (i in 0 until 100) {
- sleep(1000)
- user.userName = "lzy".plus(i)
- }
- }.start()
- }
- }
我们发现User2继承BaseObservable后,并且使用notifyPropertyChanged后,数据变动自动触发UI变化。
同其他Jetpack组件一样,databinding的使用也是一如既往的简单,但是只会使用是远远不够的,我们必须掌握其中的原理。
我们首先关注XML文件,我们写的XML文件会通过databinding自动转成另外两个文件:
文件1:
app/build/intermediates/data_binding_layout_info_type_merge/debug/out/activity_main-layout.xml
- "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.example.myapplication" rootNodeType="androidx.constraintlayout.widget.ConstraintLayout">
- <Variables name="user" declared="true" type="com.example.myapplication.User2">
- <location endLine="9" endOffset="52" startLine="7" startOffset="8" />
- Variables>
- <Targets>
- <Target tag="layout/activity_main_0"
- view="androidx.constraintlayout.widget.ConstraintLayout">
- <Expressions />
- <location endLine="27" endOffset="55" startLine="13" startOffset="4" />
- Target>
- <Target tag="binding_1" view="TextView">
- <Expressions>
- <Expression attribute="android:text" text="user.userName">
- <Location endLine="21" endOffset="42" startLine="21" startOffset="12" />
- <TwoWay>falseTwoWay>
- <ValueLocation endLine="21" endOffset="40" startLine="21" startOffset="28" />
- Expression>
- Expressions>
- <location endLine="25" endOffset="55" startLine="18" startOffset="8" />
- Target>
- Targets>
- Layout>
注:Targets里面有两个Target元素,后面会用到。
文件2:
app/build/intermediates/incremental/mergeDebugResources/stripped.dir/layout/activity_main.xml
- "1.0" encoding="utf-8"?>
- <androidx.constraintlayout.widget.ConstraintLayout 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"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:tag="layout/activity_main_0"
- tools:context=".MainActivity">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:tag="binding_1"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintLeft_toLeftOf="parent"
- app:layout_constraintRight_toRightOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
-
- androidx.constraintlayout.widget.ConstraintLayout>
我们来看看setContentView到底做了什么?
- public static
extends ViewDataBinding> T setContentView(@NonNull Activity activity, - int layoutId) {
- return setContentView(activity, layoutId, sDefaultComponent);
- }
-
- public static
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);//1
- }
我们关注注释1:
- private static
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);//1
- }
- }
再来看bind方法:
- static
extends ViewDataBinding> T bind(DataBindingComponent bindingComponent, View[] roots, - int layoutId) {
- return (T) sMapper.getDataBinder(bindingComponent, roots, layoutId);
- }
sMapper又是个什么东西呢?
private static DataBinderMapper sMapper = new DataBinderMapperImpl();
我们再进DataBinderMapperImpl里面看看:
- public class DataBinderMapperImpl extends MergedDataBinderMapper {
- DataBinderMapperImpl() {
- addMapper(new com.example.myapplication.DataBinderMapperImpl());//1
- }
- }
注释1处点进去看看:
- @Override
- 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)) {//1
- return new ActivityMainBindingImpl(component, view);//2
- }
- throw new IllegalArgumentException("The tag for activity_main is invalid. Received: " + tag);
- }
- }
- }
- return null;
- }
我们前面知道外层tag为activity_main_0,所以注意注释2处。
- public ActivityMainBindingImpl(@Nullable androidx.databinding.DataBindingComponent bindingComponent, @NonNull View root) {
- this(bindingComponent, root, mapBindings(bindingComponent, root, 2, sIncludes, sViewsWithIds));
- }
- private ActivityMainBindingImpl(androidx.databinding.DataBindingComponent bindingComponent, View root, Object[] bindings) {
- super(bindingComponent, root, 1
- );
- this.mboundView0 = (androidx.constraintlayout.widget.ConstraintLayout) bindings[0];//1
- this.mboundView0.setTag(null);
- this.mboundView1 = (android.widget.TextView) bindings[1];//2
- this.mboundView1.setTag(null);
- setRootTag(root);
- // listeners
- invalidateAll();
- }
我们来看注释1和注释2,这两个View保存在了ActivityMainBindingImpl里面,而:
ActivityMainBindingImpl extends ActivityMainBinding
所以:
- private var activityMainBinding: ActivityMainBinding? = null
-
- activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
DataBindingUtil.setContentView最终返回的activityMainBinding实际上是一个ActivityMainBindingImpl对象。
我们再来看:
activityMainBinding?.user = user
点进去,发现直接点击了布局里面,那我们直接去看ActivityMainBindingImpl的setUser方法:
- public void setUser(@Nullable com.example.myapplication.User2 User) {
- updateRegistration(0, User);//1
- this.mUser = User;//2
- synchronized(this) {
- mDirtyFlags |= 0x1L;
- }
- notifyPropertyChanged(BR.user);
- super.requestRebind();
- }
我们先来看注释2处,可见ActivityMainBindingImpl里面保存了User对象。接着点进注释1接着看:
- protected boolean updateRegistration(int localFieldId, Observable observable) {
- return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);
- }
CREATE_PROPERTY_LISTENER先标记一下,再进去看:
- protected boolean updateRegistration(int localFieldId, Object observable,
- CreateWeakListener listenerCreator) {
- if (observable == null) {
- return unregisterFrom(localFieldId);
- }
- WeakListener listener = mLocalFieldObservers[localFieldId];//1
- if (listener == null) {
- registerTo(localFieldId, observable, listenerCreator);//2
- return true;
- }
- if (listener.getTarget() == observable) {
- return false;//nothing to do, same object
- }
- unregisterFrom(localFieldId);
- registerTo(localFieldId, observable, listenerCreator);
- return true;
- }
一开始走注释1处,得到的listener为null,然后走注释2处:
- 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;//1
- if (mLifecycleOwner != null) {
- listener.setLifecycleOwner(mLifecycleOwner);
- }
- }
- listener.setTarget(observable);//2
- }
注释1处很好理解,将listener保存在mLocalFieldObservers里面。然后再将被观察者User作为target传给注释2处。
- public void setTarget(T object) {
- unregister();
- mTarget = object;
- if (mTarget != null) {
- mObservable.addListener(mTarget);
- }
- }
问题来了:mObservable是啥?我们再来看:
- private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
- @Override
- public WeakListener create(
- ViewDataBinding viewDataBinding,
- int localFieldId,
- ReferenceQueue
referenceQueue - ) {
- return new WeakPropertyListener(viewDataBinding, localFieldId, referenceQueue)
- .getListener();
- }
- };
- public WeakPropertyListener(
- ViewDataBinding binder,
- int localFieldId,
- ReferenceQueue
referenceQueue - ) {
- mListener = new WeakListener
(binder, localFieldId, this, referenceQueue); - }
- public WeakListener(
- ViewDataBinding binder,
- int localFieldId,
- ObservableReference
observable, - ReferenceQueue
referenceQueue - ) {
- super(binder, referenceQueue);
- mLocalFieldId = localFieldId;
- mObservable = observable;//1
- }
这个mObservable就是WeakPropertyListener。我们来看它的addListener方法:
- private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback
- implements ObservableReference
{ - final WeakListener
mListener; -
- public WeakPropertyListener(
- ViewDataBinding binder,
- int localFieldId,
- ReferenceQueue
referenceQueue - ) {
- mListener = new WeakListener
(binder, localFieldId, this, referenceQueue); - }
-
- @Override
- public WeakListener
getListener() { - return mListener;
- }
-
- @Override
- public void addListener(Observable target) {
- target.addOnPropertyChangedCallback(this);//1
- }
-
- @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);
- }
- }
这里的target就是被观察者User2,我们进注释1看一下(User2继承了BaseObservable):
- public class BaseObservable implements Observable {
- private transient PropertyChangeRegistry mCallbacks;
-
- public BaseObservable() {
- }
-
- @Override
- public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
- synchronized (this) {
- if (mCallbacks == null) {
- mCallbacks = new PropertyChangeRegistry();//后面会用到
- }
- }
- mCallbacks.add(callback);//1
- }
-
- @Override
- public 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
- *
BR to be used as fieldId. - *
- * @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);
- }
- }
注释1处将listener加到一个集合里面。我们接着看:
- public void setUser(@Nullable com.example.myapplication.User2 User) {
- updateRegistration(0, User);
- this.mUser = User;
- synchronized(this) {
- mDirtyFlags |= 0x1L;
- }
- notifyPropertyChanged(BR.user);//1
- super.requestRebind();
- }
进注释1:
- public void notifyPropertyChanged(int fieldId) {
- synchronized (this) {
- if (mCallbacks == null) {
- return;
- }
- }
- mCallbacks.notifyCallbacks(this, fieldId, null);//1
- }
接着进去:
- public synchronized void notifyCallbacks(T sender, int arg, A arg2) {
- mNotificationLevel++;
- notifyRecurse(sender, arg, arg2);//1
- 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;
- }
- }
- }
接着进注释1:
- 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);//1
- }
进注释1再看:
- 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);//1
- }
- bitMask <<= 1;
- }
- }
- public class PropertyChangeRegistry extends
- CallbackRegistry
{ -
- private static final CallbackRegistry.NotifierCallback
NOTIFIER_CALLBACK = new CallbackRegistry.NotifierCallback() { - @Override
- public void onNotifyCallback(Observable.OnPropertyChangedCallback callback, Observable sender,
- int arg, Void notUsed) {
- callback.onPropertyChanged(sender, arg);//1
- }
- };
-
- 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);
- }
- }
注意注释1处:
- private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback
- implements ObservableReference
{ - final WeakListener
mListener; -
- public WeakPropertyListener(
- ViewDataBinding binder,
- int localFieldId,
- ReferenceQueue
referenceQueue - ) {
- mListener = new WeakListener
(binder, localFieldId, this, referenceQueue); - }
-
- @Override
- public WeakListener
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);//1
- }
- }
又回调回了listener!进注释1处看看:
- protected void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
- if (mInLiveDataRegisterObserver || mInStateFlowRegisterObserver) {
- // We're in LiveData or StateFlow 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);//1
- if (result) {
- requestRebind();
- }
- }
再进注释1,在ActivityMainBindingImpl里面实现:
- @Override
- protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
- switch (localFieldId) {
- case 0 :
- return onChangeUser((com.example.myapplication.User2) object, fieldId);
- }
- return false;
- }
- private boolean onChangeUser(com.example.myapplication.User2 User, int fieldId) {
- if (fieldId == BR._all) {
- synchronized(this) {
- mDirtyFlags |= 0x1L;
- }
- return true;
- }
- else if (fieldId == BR.userName) {
- synchronized(this) {
- mDirtyFlags |= 0x2L;
- }
- return true;
- }
- return false;
- }
如果有变动,返回true,执行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);//1
- }
- }
- }
注释1处,切换到主线程:
- 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();//1
- }
- };
进注释1:
- public void executePendingBindings() {
- if (mContainingBinding == null) {
- executeBindingsInternal();//1
- } else {
- mContainingBinding.executePendingBindings();
- }
- }
再进注释1:
- 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 mPendingHalted
- if (mRebindHalted) {
- mRebindCallbacks.notifyCallbacks(this, HALTED, null);
- }
- }
- if (!mRebindHalted) {
- executeBindings();//1
- if (mRebindCallbacks != null) {
- mRebindCallbacks.notifyCallbacks(this, REBOUND, null);
- }
- }
- mIsExecutingPendingBindings = false;
- }
进注释1(ActivityMainBindingImpl实现):
- @Override
- protected void executeBindings() {
- long dirtyFlags = 0;
- synchronized(this) {
- dirtyFlags = mDirtyFlags;
- mDirtyFlags = 0;
- }
- com.example.myapplication.User2 user = mUser;
- java.lang.String userUserName = null;
-
- if ((dirtyFlags & 0x7L) != 0) {
-
-
-
- if (user != null) {
- // read user.userName
- userUserName = user.getUserName();
- }
- }
- // batch finished
- if ((dirtyFlags & 0x7L) != 0) {
- // api target 1
-
- androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView1, userUserName);//1
- }
- }
this.mboundView1是前面保存textView引用的地方,我们再看注释1:
- public static void setText(TextView view, CharSequence text) {
- final CharSequence oldText = view.getText();
- if (text == oldText || (text == null && oldText.length() == 0)) {
- return;
- }
- if (text instanceof Spanned) {
- if (text.equals(oldText)) {
- return; // No change in the spans, so don't set anything.
- }
- } else if (!haveContentsChanged(text, oldText)) {
- return; // No content changes, so don't set anything.
- }
- view.setText(text);//1
- }
本质上也是给TextView设置text。