LiveData原理、源码分析-粘性事件(数据倒灌)分析及解决
2023-08-16 本文已影响0人
喂_balabala
《Lifecycle原理、源码解析》
《LiveData简介及使用-什么是LiveData的粘性事件(数据倒灌)?》
- 查看LiveData的observe可知是如何绑定的
@MainThread
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);
}
- owner就是activity。这个函数就可看出已经绑定上了
- 里面有个关键函数是LifecycleBoundObserver的创建
- LifecycleBoundObserver是ObserverWrapper的子类
- ObserverWrapper有个activeStateChanged函数很关键,下面还会提到
- 记住activeStateChanged里也调用了dispatchingValue
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) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {
dispatchingValue(this);
}
}
- 再看owner.getLifecycle().addObserver(wrapper)
- 实现是在LifecycleRegister里的addObserver函数
- 里面调用了calculateTargetState,去计算当前生命周期的状态,状态更新了就会触发ObserverWrapper里面的activeStateChanged
- 这样就又执行了activeStateChanged里面的dispatchingValue函数
- 这里也是LiveData粘性事件的根源
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
if (previous != null) {
return;
}
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--;
}
- 再看LiveData类中的postValue函数
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
- postToMainThread看名字也可知post最终是传到主线程调用
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
- 再看mPostValueRunnable可知postValue最终也是调用的setValue
- 关键函数在setValue -> dispatchingValue -> considerNotify
- 由此代码顺序可看出最终就在considerNotify里调用onChanged来完成通知的
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
...
...
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
...
...
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
- setValue里面有一个mVersion,每次数据变化就加加
- considerNotify先判断当前activity是否可见,然后再判断是否还没来得及更新activity的可见状态。此知识点需先了解lifecycle
- considerNotify里面会判断mLastVersion和mVersion的值。版本不一致才会往下走,通知最新的数据变化
static final int START_VERSION = -1;
public LiveData(T value) {
mData = value;
mVersion = START_VERSION + 1;
}
/**
* Creates a LiveData with no value assigned to it.
*/
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
- 查看LiveData的构造函数可知,一般我们使用的是空参构造,所以mVersion的初始值是-1
为什么会有粘性事件?
原因:执行顺序变了
- 原来的执行顺序new LiveData-->绑定observer-->setValue执行onChanged
- 而我们的BUS在用时可能出现 new LiveData-->setValue执行onChanged-->绑定observer
- 通过setValue函数可知只要调用一次,mVersion就加一,activity还没创建,也就是还没绑定observer的时候也加一了。
- setValue会调用dispatchingValue(null),参数是null,会走里面的for循环,此时是没什么影响,因为mObservers找不到还没绑定的activity。
- 但是假如setValue发送了10次,此时mVersion就已经是10了
- 然后activity再创建,再绑定observer的时候,查看LiveData的observe函数,再查看里面的关键函数LifecycleBoundObserver的创建
- LifecycleBoundObserver是ObserverWrapper的子类
- ObserverWrapper有个activeStateChanged函数
- activeStateChanged里也调用了dispatchingValue
- 因为在绑定的时候就会监听生命周期变化,状态变了就触发状态更新
- 又会执行considerNotify,此时mVersion已经是10了,但是mLastVersion还是-1,所以就往下走,就收到了旧数据的通知
处理方案: 让第一次setValue不起效即可
- 自定义MutableLiveData,重写observe,反射修改mLastVersion的值,让它跟mVersion相等
package com.example.livedatabus;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.Observer;
import android.support.annotation.NonNull;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class LiveDataBus {
private static volatile LiveDataBus liveDataBus = null;
private Map<String, BalaLiveDataBus<Object>> map = null;
private LiveDataBus() {
map = new HashMap<>();
}
public static LiveDataBus getLiveDataBus() {
if (liveDataBus == null) liveDataBus = new LiveDataBus();
return liveDataBus;
}
public void removeData(String... keys){
for (String key : keys) {
map.remove(key);
}
}
public synchronized <T> BalaLiveDataBus<T> with(String str, Class<T> objectClass) {
if (!map.containsKey(str)) {
map.put(str, new BalaLiveDataBus<Object>());
}
return (BalaLiveDataBus<T>) map.get(str);
}
/**
* 为了不执行 MutableLiveData 中Observer的onChange方法 观察源码如下:
* <p>
* if (!observer.mActive) {
* return;
* }
* // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
* //
* // we still first check observer.active to keep it as the entrance for events. So even if
* // the observer moved to an active state, if we've not received that event, we better not
* // notify for a more predictable notification order.
* if (!observer.shouldBeActive()) {
* observer.activeStateChanged(false);
* return;
* }
* if (observer.mLastVersion >= mVersion) {
* return;
* }
* observer.mLastVersion = mVersion;
* //noinspection unchecked
* observer.mObserver.onChanged((T) mData);
* <p>
* 思路:让 observer.mLastVersion == mVersion (此修改不会改动到源码本来的逻辑)
* <p>
* 观察源码发现:
* mVersion 是 LiveData的成员变量
* observer.mLastVersion 的 observer 是 ObserverWrapper对象
* ObserverWrapper 是 Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator中的value
* iterator 相当于是 LiveData 中的成员变量 SafeIterableMap<Observer<T>, ObserverWrapper> mObservers
*
* @param <T>
*/
public static class BalaLiveDataBus<T> extends MutableLiveData<T> {
private boolean mIsViscidity = true;
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer, boolean isViscidity) {
mIsViscidity = isViscidity;
observe(owner, observer);
}
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
super.observe(owner, observer);
if (mIsViscidity) return;
try {
Class<LiveData> liveDataClass = LiveData.class;
//获取到mObservers对象
Field mObserversField = liveDataClass.getDeclaredField("mObservers");
mObserversField.setAccessible(true);
//从当前的livedata对象中获取mObservers在当前成员变量中的值
Object mObservers = mObserversField.get(this);
//获取到mObservers的类型 SafeIterableMap
Class<?> mObserversClass = mObservers.getClass();
//获取到SafeIterableMap的get方法
//get参数是一个泛型 但是又要传class对象 所以传object的
Method get = mObserversClass.getDeclaredMethod("get", Object.class);
get.setAccessible(true);
//要执行mObservers的get方法 参数是observer
//此时的对象就是 Entry<K, V>
Object invokeEntry = get.invoke(mObservers, observer);
Object observerWrapper = null;
if (invokeEntry != null && invokeEntry instanceof Map.Entry) {
observerWrapper = ((Map.Entry) invokeEntry).getValue();
}
if (observerWrapper == null) {
throw new NullPointerException("observerWrapper==null");
}
/*
*为什么要获取父类对象?因为在LiveData的observe中new的是ObserverWrapper的子类
* LifecycleBoundObserver,但是要找的mLastVersion在ObserverWrapper中
*/
Class<?> superclassWrapper = observerWrapper.getClass().getSuperclass();
Field mLastVersion = superclassWrapper.getDeclaredField("mLastVersion");
mLastVersion.setAccessible(true);
Field mVersion = liveDataClass.getDeclaredField("mVersion");
mVersion.setAccessible(true);
//从当前的livedata对象中获取mVersion的值
Object o = mVersion.get(this);
//mVersion的值给mLastVersion mLastVersion是在observerWrapper里面的
mLastVersion.set(observerWrapper, o);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}