LiveData的工作原理分析
Posted mChenys
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LiveData的工作原理分析相关的知识,希望对你有一定的参考价值。
文章目录
一、简介
LiveData是一个数据持有类,它可以通过添加观察者被其他组件观察其变更。不同于普通的观察者,它最重要的特性就是遵从应用程序的生命周期,如在Activity中如果数据更新了但Activity已经是destroy状态,LivaeData就不会通知Activity(observer)。当然LiveData的优点还有很多,如不会造成内存泄漏等。LiveData通常会配合ViewModel来使用,ViewModel负责触发数据的更新,更新会通知到LiveData,然后LiveData再通知活跃状态的观察者。
二、数据监听源码分析
2.1 LiveData的observer方法分析
直接从observe方法入手
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
// 判断是否在主线程,不是则报错
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore 如果Activity/fragment已经销毁了,那么忽略
return;
}
// 重点代码,包装了一个LifecycleBoundObserver,将外部出入的owner和observer封装了一层
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// 重点代码,mObservers=SafeIterableMap<Observer<? super T>, ObserverWrapper>,可以把它看作Map
// 这里的目的就是尝试保存到map,返回值可以用来判断是第一次添加还是说之前已经添加过
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
// 如果返回值存在,那么说明不是第一次put到Map缓存中,那么避免重复添加,这里直接抛出异常了
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
// 已经添加过观察者,直接返回
return;
}
// 如果owner没有添加过观察者,那么才添加,注意这里添加的并不是我们外面传入的,而已经过包装过后的LifecycleBoundObserver
// 当添加了Lifecycle的观察者后,LifecycleBoundObserver就能感知owner的生命周期了
owner.getLifecycle().addObserver(wrapper);
}
2.2 LifecycleBoundObserver源码分析
下面就来看看LifecycleBoundObserver到底是何方神圣
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner; // 真正的外部传入的LifecycleOwner
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer); // 这里将外部传入的观察者传给了父类ObserverWrapper
mOwner = owner;
}
@Override
boolean shouldBeActive() {
// 这里状态要start之后才表示激活了
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
// 实现GenericLifecycleObserver的接口方法,由LifeCycler回调
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
// 当目标不可见的时候调用liveData的removeObserver方法,将外部传入的观察者移除掉
removeObserver(mObserver);
return;
}
// 重点代码:通知父类ObserverWrapper状态变化,后面会介绍
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
// 是否添加到目标owner中
return mOwner == owner;
}
@Override
void detachObserver() {
// 目标lifeCycle异常观察者,注意传入的是this,也就是包装后的
mOwner.getLifecycle().removeObserver(this);
}
}
上面代码并不多,LifecycleBoundObserver 继承自LiveData的内部类ObserverWrapper 并实现了 GenericLifecycleObserver接口,而 GenericLifecycleObserver 接口又继承自 LifecycleObserver 接口,那么根据 Lifecycle 的特性,实现了LifecycleObserver接口并且加入 LifecycleOwner 的观察者里就可以感知或主动获取 LifecycleOwner 的状态。
2.3 ObserverWrapper源码分析
我们来看看ObserverWrapper源码
// 这是定义在LiveData内部的抽象类
private abstract class ObserverWrapper {
// 这里的观察者其实就是我们外面传入的,也就是它的子类LifecycleBoundObserver的构造方法赋值的
final Observer<? super T> mObserver;
boolean mActive; // 标记是否激活了
// 重点代码,标记最后一次发送数据的版本,默认是-1
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer; // 子类继承后需要调用usper来赋值
}
// 抽象方法,由子类LifecycleBoundObserver实现
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;// 默认是false,子类会重写此方法
}
void detachObserver() {
}
// 重点方法:也是由子类调用,用来更新状态,当子类的生命周期状态监听发生变化就会回调到这里
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
// 状态相同,忽略
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive; // 更新状态
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
// 回调给LiveData,当前是激活状态
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
// 回调给LiveData,当前是非激活状态
onInactive();
}
if (mActive) {
// 如果激活了,调用下面方法进行分发,后面会重点介绍,这个方法是LiveData的方法
dispatchingValue(this);
}
}
}
2.4 LifecycleEventObserver接口分析
来看看LifecycleEventObserver接口,很简单,只是继承了LifecycleObserver,并且提供了一个方法用来通知状态变更
public interface LifecycleEventObserver extends LifecycleObserver {
/**
* Called when a state transition event happens.
*
* @param source The source of the event
* @param event The event
*/
void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
分析到这里,我们可以清楚的知道,当我们调用LiveData的observer的时候其实是调用了owner的getLifecycle().addObserver添加了一个经过包装后的LifecycleBoundObserver观察者
三、数据发送源码分析
3.1 LiveData的postValue/setValue方法分析
看完了上面观察者的注册分析后,那么我们的LiveData什么时候会通知观察者呢?不用想,肯定是数据更新的时候,而数据的更新是我们代码自己控制的,如请求网络返回User信息后,我们会主动将User放入MutableLiveData中,这个时候就要用到postValue或者setValue方法了,由于LiveData是一个抽象类且这2个方法都是protected的,而它的子类MutableLiveData中是重写了这2个方法的.
public class MutableLiveData<T> extends LiveData<T> {
// 带参数构造方法
public MutableLiveData(T value) {
super(value);
}
public MutableLiveData() {
super();
}
@Override
public void postValue(T value) {
super.postValue(value); // 调用super方法
}
@Override
public void setValue(T value) {
super.setValue(value); // 调用super方法
}
}
来看看父类做了啥
static final int START_VERSION = -1;
private volatile Object mData; // 维护的数据
private int mVersion = START_VERSION; // 维护的版本,每次发送数据都会自增
// 运行在子线程
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
/// 发送到主线程中
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
// 最终还是调用下面的setValue方法发送数据
setValue((T) newValue);
}
};
// 运行在主线程
@MainThread
protected void setValue(T value) {
assertMainThread("setValue"); // 判断是否在主线程
mVersion++; // 重点代码,版本自增
mData = value; // 保存数据
// 重点方法
dispatchingValue(null);
}
3.2 LiveData的dispatchingValue方法分析
可以看到调用 dispatchingValue()方法并传入null,表示将数据分发给各个观察者, 下面来分析此方法的具体逻辑
private boolean mDispatchingValue; // 标记当前是否正在分发数据
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
// 更新标记
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
// 标注1:如果传入的不是null,那么调用下面的方法通知观察者
// 还记得上面分析ObserverWrapper源码的activeStateChanged方法吗
// 没错当LifecycleBoundObserver监听到owner状态变化后会调用其父类ObserverWrapper的activeStateChanged方法,
// 然后activeStateChanged方法会在mActive=true的时候调用considerNotify方法
considerNotify(initiator);
initiator = null;
} else {
// initiator=null进来
// 否则遍历所有的观察者,还记得这里的map吗,他就是mObservers,key=observer,value=LifecycleBoundObserver
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
//标注2: 通知所有的LifecycleBoundObserver
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
3.3 LiveData的considerNotify方法分析
从标注1可以看出,dispatchingValue()参数传null和不传null的区别就是如果传null将会通知所有的观察者,反之仅仅通知传入的观察者。我们直接看标注2,通知所有的观察者通过遍历 mObservers ,将所有的 ObserverWrapper 拿到,实际上就是我们上面提到的 LifecycleBoundObserver,通知观察者调用considerNotify()方法,这个方法就是通知的具体实现了。
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
// 如果LifecycleBoundObserver维护的状态,切切来说是它的父类ObserverWrapper的mActive=false,那么忽略数据的发送
return;
}
// 这里通过observer.shouldBeActive间接的判断owner的状态,这里主动调用一次也是为了保证状态更加精确
// 因为上面的observer.mActive判断是被动监听的
if (!observer.shouldBeActive()) {
// 如果owner的状态不可见,那么通知状态变化,更新的observer.mActive的值=false
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
// 重点方法,对比LifecycleBoundObserver的mLastVersion版本和LiveData的版本mVersion,如果相同或者大于LiveData的,则忽略数据的发送
return;
}
// 上面经过重重筛选后来到这里,说明是需要发送数据,更新mLastVersio的版本
// 而mVersion的值在上面分析postValue方法的时候我们知道每次调用的时候都会自增
observer.mLastVersion = mVersion;
// 通知真正的观察者,也就是我门注入的观察者,它维护在LifecycleBoundObserver中
observer.mObserver.onChanged((T) mData);
}
如果观察者不是活跃状态,将不会通知此观察者,看最后一行,observer.mObserver.onChanged((T) mData),observer.mObserver就是我们调用LiveData的observer()方法传入的 Observer,然后调用 Observer 的 onChanged((T) mData)方法,将保存的数据mData传入,也就实现了更新。在看下我们实现的Observer:
viewModel.getUser().observe(MainActivity.this, new Observer<User>() {
@Override
public void onChanged(@Nullable User user) {
if (user != null) {
tvUser.setText(user.toString());
}
}
});
如果哪个控件要根据user的变更而及时更新,就在onChanged()方法里处理就可以了。到这里,LiveData已经能够分析完了,其实LiveData的实现还是要依赖于Lifecycle。
四、LiveData的粘性事件
4.1 何为粘性事件
即发射的事件如果早于注册,那么注册之后依然可以接收到的事件称为粘性事件。
4.2 发生粘性事件的原因
粘性事件通常会出现在多个页面共用同一个单例的LiveData对象的场景,究其原因就是因为LiveData的mVersion大于LifecycleBoundObserver的mLastVersion导致的。因为LiveData的mVersion是用来标记发送数据的次数的,每调用一次postValue或者setValue方法就会让mVersion自增一次,而前面分析源码的时候我门知道当mVersion > mLastVersion的时候就会将数据发送给我们设置的观察者的onChanged方法。
至于为什么初次设置监听会出现mVersion > mLastVersion的情况呢?
首先我需要说明下,mVersion和mLastVersion的默认值都是等于START_VERSION常量,它的值就是-1, 因此我们第一次使用LiveData肯定是mVersion=mLastVersion=-1的,因此首次设置observer进行监听的时候是不会出现粘性事件。
但是,如果现在有2个Activity页面分别是A页面和B页面,A和B页面都是同时使用一个单例的LiveData对象,下面开始分析:
-
A页面设置监听,同时发送一次数据,那么LiveData的mVersion+1后变成0, 同时A页面设置observer会收到通知,因为LifecycleBoundObserver第一次添加到Lifecycler的时候,它的mLastVersion=-1,因此满足mVersion>mLastVersion, 所有A页面能收到通知,而此时B页面还没有打开,所以并没有触发添加监听的操作,因此B收不到通知。
-
A页面跳到B页面,B页面在onCreate使用同一个LiveData进行事件的observer监听,它会立刻收到粘性事件,因为此时的LiveData的mVersion变成了0, 而B页面Lifecycler在注册observer的时候也是一个新的LifecycleBoundObserver, 即mLastVersion是-1,因此满足mVersion>mLastVersion,所以B页面收到粘性事件。
4.3 从源码角度分析粘性事件
由于粘性事件是在设置observer的时候发生,因此我们还是从LiveData的observer方法入手分析
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
// 上面我们都分析过了,这里就不分析了,重点来分析下面这行代码
owner.getLifecycle().addObserver(wrapper);
}
此处getLifeCycle获取的对象是LifecycleRegistry对象,查看AppcompatActivity的getLifecycle方法就可以知道原因了,它最终会调用ComponentActivity的getLifecycle方法
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
...
// 这里可知mLifecycleRegistry就是LifecycleRegistry对象
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
public Lifecycle getLifecycle() {
// 返回一个mLifecycleRegistry对象
return mLifecycleRegistry;
}
}
因此,我们需要来分析LifecycleRegistry的addObserver方法
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
// 判断状态
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
// 这里将LifecycleBoundObserver又进行了一次包装
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
// 然后保存到map中
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
if (previous != null) {
// 同样的道理,如果缓存存在,直接返回
return;
}
// 从WeakReference中获取LifecycleOwner
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
// it is null we should be destroyed. Fallback quickly
return; // 获取不到返回
}
boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
// 关键代码
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
if (!isReentrance) {
// we do sync only on the top level.
sync();
}
mAddingObserverCounter--;
}
分析上面的关键代码,也就是ObserverWithState的dispatchEvent方法
static class ObserverWithState {
State mState;
LifecycleEventObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
// 关键代码,回调LifecycleBoundObserver的onStateChanged方法
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
}
当LifecycleBoundObserver的onStateChanged方法触发后就会触发父类的ObserverWrapper的activeStateChanged方法,activeStateChanged又会触发dispatchingValue方法,而最终会触发considerNotify方法,这个过程熟悉吧,我们上面分析LiveData原理的时候也分析到了,而且重点分析了dispatchingValue方法,当他传入null的时候会分发所有的观察者,当传入具体的ObserverWrapper时就会只会单独回调该ObserverWrapper,这里分析首次注册观察者的时候刚好对应的就是这种情况。
由上面分析得知,但我们首次调用LiveData的observer方法进行观察者注册的时候,其实是会触发LiveData的considerNotify方法触发的,这也就为粘性事件的分发提供了先天条件, 而必要条件就是mVersion > mLastVersion.
4.4 如何避免粘性事件
既然已经知道了原因,那么怎么解决呢? 我这里介绍2种方案:
1、因为每个LiveData都维护了一个mVersion,为了避免影响,我们在注册观察者的时候使用不同的LiveData对象就可以避免相互影响了.
2、自己维护LiveData和mVersion和ObserverWrapper的mLastVersion,这就需要我们重写LiveData了.
这里介绍方式2, 代码如下:
public class BaseLiveData<T> extends MutableLiveData<T> {
private int mVersion = -以上是关于LiveData的工作原理分析的主要内容,如果未能解决你的问题,请参考以下文章
4. Jetpack源码解析—LiveData的使用及工作原理
4. Jetpack源码解析—LiveData的使用及工作原理
4. Jetpack源码解析—LiveData的使用及工作原理