在使用databinding时,更新UI界面,如果是使用普通变量的,那么在变量发生变化的时候,UI界面并不会发生变化
数据变化是视图也跟着变化则需要使用到以下两种方法
BaseObservable,
ObservableBoolean,
ObservableByte,
ObservableChar,
ObservableDouble,
ObservableField<T>,
ObservableFloat,
ObservableInt,
ObservableLong,
ObservableParcelable<T extends Parcelable>,
ObservableShort,
ViewDataBinding
为了方便我们暂且把这种可以让视图跟随数据刷新的类型,叫做databinding变量
这里不再介绍这些,可以去网上搜相关内容或者参考链接
通过表达式使用@=
表达式就可以视图刷新的时候自动更新数据
这种双向绑定存在一个很大的问题就是会死循环。 数据变化(回调监听器)触发视图变化, 然后视图又会触发数据变化(再次回调监听器), 然后一直循环, 设置相同的数据也视为数据变化.
为什么使用这些变量,视图可以根据数据而变化呢?双向绑定的时候,是如何避免死循环的呢?在使用databinding时,经常遇到各种错误,如果对源码熟悉,就可以迅速定位问题并解决。所以理解源码是很有必要的。
更新视图的源码,主要按变量类型分为四类, Observable ,ObservableList ,ObservableMap ,LiveData> 源码大同小异,这里以ObservableField为例进行分析
编译后,会自动在路app\build\generated\source\kapt\debug\com\xhd\xiaohuangdian\databinding\FragmentAbstractTotalBindingImpl.java
生成对应的代码,其中主干流程就是下面三个函数。
DataBinding 使用观察者模式,当数据发生变化的时候,对UI进行更新,那么我们看一下观察者注册订阅者的流程
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);
//这行代码,最后会执行到executeBindings()
super.requestRebind();
}
2、在executeBindings中进行 订阅,数据发生变化也会调用。
@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);
}
观察者订阅和更新UI都是通过上面这个函数来完成,
如果你看了代码,会有疑问,难道每次更新数据的是否都会去再订阅一次吗?
是的,因为这个观察者是个弱引用,很可能被系统回收了,所以每次更新数据时都会再去订阅一次。如果订阅关系没有发生变化,则直接返回false(详解下面的代码)
3、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
的第三个参数是CreateWeakListener 接口类型的。只有一个create()函数,返回类型是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();
}
};
4、WeakListener 是在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);
}
}
WeakListener 有一个WeakPropertyListener类型的变量mObservable, 是一个弱引用类,防止内存泄漏。所以后面的操作,都是通过它的对象来操作。
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
// observable 参数是ObservableBoolean 类型的,是业务中的值
// listenerCreator 上面四种CreateWeakListener 之一,通过它的create 可以获取到WeakListener ,WeakListener 的参数mObservable 是WeakPropertyListener类型
private boolean updateRegistration(int localFieldId, Object observable,
CreateWeakListener listenerCreator) {
if (observable == null) {
return unregisterFrom(localFieldId);
}
//将WeakListener 变量保存在mLocalFieldObservers 因为WeakListener是弱引用,所以需要判空,如果是空的就注册
WeakListener listener = mLocalFieldObservers[localFieldId];
if (listener == null) {
registerTo(localFieldId, observable, listenerCreator);
return true;
}
//listener 和相同的tatget 注册过了,就不需要再注册了
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);
来创建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);
//这里把新创建的WeakListener 保存在数组,方便下次使用
mLocalFieldObservers[localFieldId] = listener;
if (mLifecycleOwner != null) {
listener.setLifecycleOwner(mLifecycleOwner);
}
}
//listener 是WeakListener ,
listener.setTarget(observable);
}
7、分析一下,上段代码listener.setTarget(observable);
就是调用WeakListener的setTarget
,
WeakListener中的setTarget
//这里的T 参数是ObservableBoolean 类型的,是业务中的值
public void setTarget(T object) {
unregister();
mTarget = object;
if (mTarget != null) {
// mObservable 就是WeakPropertyListener
// 通过WeakListener 里面的参数来使用WeakPropertyListener,就是保证WeakListener 可以在内存吃紧的时候,可以被回收
mObservable.addListener(mTarget);
}
}
调用了WeakPropertyListener的addListener
@Override
public void addListener(Observable target) {
//参数是`OnPropertyChangedCallback` 类型,这里传入的参数是this,因为**WeakPropertyListener**变量,实现了接口`OnPropertyChangedCallback`
//target 是Observable 类型 (ObservableBoolean的父类)
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();
}
}
//终于到了观察者订阅的地方,(本例子来看,BaseObservable 就是ObservableBoolean)
// 相当于把一个观察者 callback,与订阅者BaseObservable ,建立联系,当BaseObservable 的数据发生变化,通知到callback,实现相应的UI更新
mCallbacks.add(callback);
}
...省略部分函数...
/**
* Notifies listeners that all properties of this instance have changed.
* databinding 变量的数据发生变化后,最先会调用到这里
*/
public void notifyChange() {
synchronized (this) {
if (mCallbacks == null) {
return;
}
}
//这一句代码,最终会调用到下面的第9点的callback.onPropertyChanged(sender, arg);
mCallbacks.notifyCallbacks(this, 0, null);
}
...省略部分函数...
}
9、上面的创建了PropertyChangeRegistry,来看一下它都做了些什么
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) {
//数据更新后,调用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、onFieldChange 回调到 XXXXBindingImpl.java
类中调用
@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;
}
15、来看一下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等等,在这个基础上去理解这些细节会容易一些。