在使用databinding时,更新UI界面,如果是使用普通变量的,那么在变量发生变化的时候,UI界面并不会发生变化
一、数据绑定
视图跟随数据刷新
数据变化是视图也跟着变化则需要使用到以下两种方法
- 继承BaseObservable
- ObservableField,databinding默认实现了一系列实现Observable接口的字段类型
BaseObservable,
ObservableBoolean,
ObservableByte,
ObservableChar,
ObservableDouble,
ObservableField<T>,
ObservableFloat,
ObservableInt,
ObservableLong,
ObservableParcelable<T extends Parcelable>,
ObservableShort,
ViewDataBinding
- MutableLiveData
Android 最近推出的Android Jetpack 其中的livedata也支持数据更新时,视图也能更新。
为了方便我们暂且把这种可以让视图跟随数据刷新的类型,叫做databinding变量
这里不再介绍这些,可以去网上搜相关内容或者参考链接
数据跟随视图刷新
通过表达式使用@=
表达式就可以视图刷新的时候自动更新数据
这种双向绑定存在一个很大的问题就是会死循环。 数据变化(回调监听器)触发视图变化, 然后视图又会触发数据变化(再次回调监听器), 然后一直循环, 设置相同的数据也视为数据变化.
二、源码分析
为什么使用这些变量,视图可以根据数据而变化呢?双向绑定的时候,是如何避免死循环的呢?在使用databinding时,经常遇到各种错误,如果对源码熟悉,就可以迅速定位问题并解决。所以理解源码是很有必要的。
更新视图的源码,主要按变量类型分为四类, Observable ,ObservableList ,ObservableMap ,LiveData<?> 源码大同小异,这里以ObservableField为例进行分析
ObservableField更新视图源码分析
编译后,会自动在路app\build\generated\source\kapt\debug\com\xhd\xiaohuangdian\databinding\FragmentAbstractTotalBindingImpl.java
生成对应的代码,其中主干流程就是下面三个函数。
1、设置变量,让变量此时的值显示到UI上
@Override
public boolean setVariable(int variableId, @Nullable Object variable) {
boolean variableSet = true;
if (BR.fragment == variableId) {
setFragment((com.xhd.xiaohuangdian.ui.home.AbstractTotalFragment) variable);
}
else if (BR.viewModel == variableId) {
setViewModel((com.xhd.xiaohuangdian.vm.home.TotalVM) variable);
}
else {
variableSet = false;
}
return variableSet;
}
//如果Fragment类中,没有其他的databinding变量,会生成如下的setxxxxx函数
public void setFragment(@Nullable com.xhd.xiaohuangdian.ui.home.AbstractTotalFragment Fragment) {
this.mFragment = Fragment;
}
//如果ViewModel类中,有其他的databinding变量,会生成如下的setxxxxx函数
public void setViewModel(@Nullable com.xhd.xiaohuangdian.vm.home.TotalVM ViewModel) {
this.mViewModel = ViewModel;
synchronized(this) {
mDirtyFlags |= 0x4L;
}
notifyPropertyChanged(BR.viewModel);
//这行代码,最终会执行到本篇的第三段代码
super.requestRebind();
}
2、当变量的值发生变化的时候,最终会调用这个函数,下面会通过源码来介绍,是如何调用到这里的
@Override
protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
switch (localFieldId) {
case 0 :
return onChangeViewModelIsLoading((androidx.databinding.ObservableBoolean) object, fieldId);
}
return false;
}
private boolean onChangeViewModelIsLoading(androidx.databinding.ObservableBoolean ViewModelIsLoading, int fieldId) {
if (fieldId == BR._all) {
synchronized(this) {
//脏标志位,数据更新后,用于在第三段代码中判断哪些if语句需要执行
mDirtyFlags |= 0x1L;
}
return true;
}
return false;
}
3、数值发生变化后,会调用该函数,来对UI进行更新
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
//脏标志位,初始的脏标志位为全1,为了让下面所有的if都可以执行,非第一次执行(数据改变后的执行),会根据这个脏标志位来判断执行那个if
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
boolean viewModelIsLoadingGet = false;
androidx.databinding.ObservableBoolean viewModelIsLoading = null;
com.xhd.xiaohuangdian.vm.home.TotalVM viewModel = mViewModel;
if ((dirtyFlags & 0xdL) != 0) {
if (viewModel != null) {
// read viewModel.isLoading
viewModelIsLoading = viewModel.isLoading();
}
updateRegistration(0, viewModelIsLoading);
if (viewModelIsLoading != null) {
// read viewModel.isLoading.get()
viewModelIsLoadingGet = viewModelIsLoading.get();
}
}
// batch finished
if ((dirtyFlags & 0xdL) != 0) {
// api target 1
this.mboundView0.setPbEnable(viewModelIsLoadingGet);
}
executeBindingsOn(mboundView0);
}
4、一般我们在代码中使用databinding,类里包含databinding变量,一般会先调用setVariable
,最终会执行到第三段代码。
第三段代码中,updateRegistration(0, viewModelIsLoading);
可以理解为创建了一个监听。如果数据发生变化后,就会去执行第二段和第三段代码。
updateRegistration 有四种类型,主要就是参数类型不一样,四种参数分别对应于Observable ,ObservableList ,ObservableMap ,LiveData<?>,也就是上面所说的databinding变量
源码如下:
/**
* @hide
*/
protected boolean updateRegistration(int localFieldId, Observable observable) {
return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);
}
/**
* @hide
*/
protected boolean updateRegistration(int localFieldId, ObservableList observable) {
return updateRegistration(localFieldId, observable, CREATE_LIST_LISTENER);
}
/**
* @hide
*/
protected boolean updateRegistration(int localFieldId, ObservableMap observable) {
return updateRegistration(localFieldId, observable, CREATE_MAP_LISTENER);
}
/**
* @hide
*/
protected boolean updateLiveDataRegistration(int localFieldId, LiveData<?> observable) {
mInLiveDataRegisterObserver = true;
try {
return updateRegistration(localFieldId, observable, CREATE_LIVE_DATA_LISTENER);
} finally {
mInLiveDataRegisterObserver = false;
}
}
上面updateRegistration
的第三个参数,对应下面WeakPropertyListener,WeakListListener,WeakMapListener,LiveDataListener。注意这四个类实现的接口都是一样的,而且都有一个类型为WeakListener 的变量
/**
* Method object extracted out to attach a listener to a bound Observable object.
*/
private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
@Override
public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
}
};
/**
* Method object extracted out to attach a listener to a bound ObservableList object.
*/
private static final CreateWeakListener CREATE_LIST_LISTENER = new CreateWeakListener() {
@Override
public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
return new WeakListListener(viewDataBinding, localFieldId).getListener();
}
};
/**
* Method object extracted out to attach a listener to a bound ObservableMap object.
*/
private static final CreateWeakListener CREATE_MAP_LISTENER = new CreateWeakListener() {
@Override
public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
return new WeakMapListener(viewDataBinding, localFieldId).getListener();
}
};
/**
* Method object extracted out to attach a listener to a bound LiveData object.
*/
private static final CreateWeakListener CREATE_LIVE_DATA_LISTENER = new CreateWeakListener() {
@Override
public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
return new LiveDataListener(viewDataBinding, localFieldId).getListener();
}
};
这里只查看一下WeakPropertyListener 的源码,其他大同小异
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) {
}
//数据更新后,回调到这里去更新UI,下接第12段
@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是类型WeakListener,源码如些,其中的mObservable是WeakPropertyListener
private static class WeakListener<T> extends WeakReference<ViewDataBinding> {
private final ObservableReference<T> mObservable;
protected final int mLocalFieldId;
private T mTarget;
public WeakListener(ViewDataBinding binder, int localFieldId,
ObservableReference<T> observable) {
super(binder, sReferenceQueue);
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;
}
protected ViewDataBinding getBinder() {
ViewDataBinding binder = get();
if (binder == null) {
unregister(); // The binder is dead
}
return binder;
}
}
5、updateRegistration
的源码,进行一些判断,最终去执行registerTo
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;
}
if (listener.getTarget() == observable) {
return false;//nothing to do, same object
}
unregisterFrom(localFieldId);
registerTo(localFieldId, observable, listenerCreator);
return true;
}
6、注册监听,如果WeakListener 为空,就是创建listenerCreator.create(this, localFieldId);
,这里的create
就是第四段代码中的create
函数,获得了WeakListener变量。最后调用 listener.setTarget(observable);
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);
mLocalFieldObservers[localFieldId] = listener;
if (mLifecycleOwner != null) {
listener.setLifecycleOwner(mLifecycleOwner);
}
}
listener.setTarget(observable);
}
7、分析一下,上段代码listener.setTarget(observable);
就是调用WeakListener(源码在第4点已经给出)的setTarget
,
WeakListener中的setTarget,mObservable就是WeakPropertyListener 的对象
public void setTarget(T object) {
unregister();
mTarget = object;
if (mTarget != null) {
mObservable.addListener(mTarget);
}
}
实际是调用了WeakPropertyListener的addListener
,参数是OnPropertyChangedCallback
类型,这里传入的参数是this,因为WeakPropertyListener变量,实现了接口OnPropertyChangedCallback
@Override
public void addListener(Observable target) {
target.addOnPropertyChangedCallback(this);
}
8、target.addOnPropertyChangedCallback(this);
调用了BaseObservable 的addOnPropertyChangedCallback
函数
public class BaseObservable implements Observable {
private transient PropertyChangeRegistry mCallbacks;
public BaseObservable() {
}
//这里的参数callback,就是WeakPropertyListener变量,因为它实现了接口OnPropertyChangedCallback
@Override
public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
synchronized (this) {
if (mCallbacks == null) {
mCallbacks = new PropertyChangeRegistry();
}
}
mCallbacks.add(callback);
}
...省略部分函数...
/**
* Notifies listeners that all properties of this instance have changed.
* databinding 变量的数据发生变化后,最先会调用到这里
*/
public void notifyChange() {
synchronized (this) {
if (mCallbacks == null) {
return;
}
}
mCallbacks.notifyCallbacks(this, 0, null);
}
...省略部分函数...
}
9、上面的创建了PropertyChangeRegistry,来看一下它都做了些什么,
- 实现了一个接口到变量NOTIFIER_CALLBACK
- 这个类是继承CallbackRegistry,调用
super(NOTIFIER_CALLBACK);
把这个接口的实现,传递给CallbackRegistry的变量mNotifier,mNotifier主要是在databinding变量数据更新后,回调的时候使用,下面会介绍到。
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) {
//数据更新后,调用第4段中的WeakPropertyListener的onPropertyChanged()
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);
}
}
10、到这里,基本上注册监听的事情都完成了,接下来看一下,如果数据发生变化,是怎么用已经创建好的监听去更新UI的。
数据发生变化,例如调用:ObservableField系列的set()
public void set(boolean value) {
//这里的判断,避免了双向绑定的死循环
if (value != mValue) {
mValue = value;
//数据更新后,这个函数就是第8段代码的notifyChange()
notifyChange();
}
}
11、第8段代码的notifyChange()
调用的mCallbacks.notifyCallbacks(this, 0, null);
最终会到下面这段代码,这里的mNotifier就是第9段代码的PropertyChangeRegistry 的父类变量
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) {
//数据更新后,调用PropertyChangeRegistry中的接口变量的函数
mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg, arg2);
}
bitMask <<= 1;
}
}
12、分析一下mNotifier.onNotifyCallback
,其中mNotifier 就是PropertyChangeRegistry 中的NOTIFIER_CALLBACK(看第9段代码),调用callback.onPropertyChanged(sender, arg);——>调用第4段中的WeakPropertyListener的onPropertyChanged()
13、第4段代码中的, binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
调用了下面的这个函数,onFieldChange()
是一个抽象函数,它的实现类,就是编译时候生成的xxxxxBindingImpl.java,因此就是调用第2段代码中的onFieldChange()
,判断是否需要改变,最终在 requestRebind();
中调用了第3段代码 executeBindings()
实现了对UI的更新
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();
}
}
14、来看一下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;
}
//boolean USE_CHOREOGRAPHER = SDK_INT >= 16;
if (USE_CHOREOGRAPHER) {
mChoreographer.postFrameCallback(mFrameCallback);
} else {
mUIThreadHandler.post(mRebindRunnable);
}
}
}
注意这里更新UI是异步的,所以在java代码中,更新databinding的数据,之后马上又去设置ui值,可能最后会被databinding的值覆盖。
异步执行的Runnable ,代码如下
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();
}
};
下面的代码很简单,看注释的那几句关键代码
public void executePendingBindings() {
if (mContainingBinding == null) {
//执行了这句代码
executeBindingsInternal();
} else {
mContainingBinding.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 mPendingHalted
if (mRebindHalted) {
mRebindCallbacks.notifyCallbacks(this, HALTED, null);
}
}
if (!mRebindHalted) {
//这里最终会调用到第三段代码,对UI进行更新
executeBindings();
if (mRebindCallbacks != null) {
mRebindCallbacks.notifyCallbacks(this, REBOUND, null);
}
}
mIsExecutingPendingBindings = false;
}
这介绍了databinding的主要流程,其中包括一些其他的细节,例如脏标志位mDirtyFlags,LifecycleOwner等等,在这个基础上去理解这些细节会容易一些。