先思考几个问题
livedata是怎么做的监听生命周期的 ?
postValue和setValue有什么区别 ?
事件是如何发送和接收的?
livedata粘性事件是什么 ?
livedata的粘性事件是怎样引起的 ?
首先需要知道注册监听和发送事件的几个方法 observe,postvalue,setvalue,我们主要是对这几个方法进行分析
livedata发送事件的方法有两种 postValue和setValue
我们先来看setValue
@Override
public void setValue(T value) {
super.setValue(value);
}
@MainThread
protected void setValue(T value) {
assertMainThread("setValue"); // 确保是在主线程,否则抛出异常
mVersion++; // 版本号加1,这里很重要
mData = value; // 保存值
dispatchingValue(null); // 分发消息(注意这个方法)
}
setValue看完了,接下来看postValue
@Override
public void postValue(T value) {
super.postValue(value);
}
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) { // 保证线程安全,保存value值
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((T) newValue);
}
};
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = createAsync(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
总结 : postValue其实也是通过的setValue发送消息,不同的是,postValue通过handler进行了线程切换,这样在子线程中发送消息也不会报错,而setValue会直接抛出异常
看完了事件的发送,我们来看事件接收,注意到上面发送事件时会调用到dispatchingValue方法,这个很关键
要分析事件的接收,我们首先来看是如何注册监听的
mObservers.putOfAbsent
@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);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
dispatchingValue(this);
}
}
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);
}
所谓的粘性是数据发送早于注册监听,当我们进行注册observe时,回调了上一次的老数据,从代码的层面来看,先调用了setValue将mVersion进行++,然后注册监听,当生命周期活跃时,会调用到considerNotify,而此时的mLastVersion时初始值-1,if条件不成立,进而调用onChanged接收了上一次数据
这里得满足两个条件会触发粘性事件
1.数据发送早于注册监听
2.监听者的owner生命周期进入活跃状态
livedata是被观察者,mObservers是观察者集合
要注意,mVersion存放在livedata中,而mLastVersion存放在livedata的被观察者中
从源码里分析很容易知道。我们只需要修改mLastVersion值,使得第一次的if条件成立就OK,具体的实现就是通过反射,找到ObserverWrapper修改它的mLastVersion的值
具体实现代码
private fun hook(observer: Observer<*>) {
runCatching {
val liveDataClazz = LiveData::class.java
val mapClazz = SafeIterableMap::class.java
val getMethod: Method = mapClazz.getDeclaredMethod("get", Any::class.java)
getMethod.isAccessible = true
val observerField = liveDataClazz.getDeclaredField("mObservers")
observerField.isAccessible = true
val observers = observerField.get(this)
val invokeEntry = getMethod.invoke(observers, observer)
var boundObserver: Any? = null
if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
boundObserver = invokeEntry.value
}
if (boundObserver == null) {
throw NullPointerException("boundObserver 为空")
}
val observerWrapperClazz: Class<*> = boundObserver.javaClass.superclass
val mLastVersionField: Field = observerWrapperClazz.getDeclaredField("mLastVersion")
mLastVersionField.isAccessible = true
val mVersionField: Field = liveDataClazz.getDeclaredField("mVersion")
mVersionField.isAccessible = true
val mVersionValue: Any = mVersionField.get(this)!!
mLastVersionField.set(boundObserver, mVersionValue)
}.onFailure {
it.printStackTrace()
}
}
object LiveDataBus {
private val busMap: MutableMap<String, BusMutableLivedata<Any>> by lazy { HashMap() }
@Suppress("UNCHECKED_CAST")
@Synchronized
fun <T> with(key: String, type: Class<T>, isStick: Boolean = false): BusMutableLivedata<T> {
if (!busMap.containsKey(key)) {
busMap[key] = BusMutableLivedata(isStick)
}
(busMap[key] as BusMutableLivedata<T>).isStick = isStick
return busMap[key] as BusMutableLivedata<T>
}
class BusMutableLivedata<T> private constructor() : MutableLiveData<T>() {
var isStick: Boolean = false // 默认取消粘性事件
constructor(isStick: Boolean) : this() {
this.isStick = isStick
}
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
super.observe(owner, observer)
if (!isStick) {
hook(observer)
}
}
private fun hook(observer: Observer<*>) {
runCatching {
val liveDataClazz = LiveData::class.java
val mapClazz = SafeIterableMap::class.java
val getMethod: Method = mapClazz.getDeclaredMethod("get", Any::class.java)
getMethod.isAccessible = true
val observerField = liveDataClazz.getDeclaredField("mObservers")
observerField.isAccessible = true
val observers = observerField.get(this)
val invokeEntry = getMethod.invoke(observers, observer)
var boundObserver: Any? = null
if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
boundObserver = invokeEntry.value
}
if (boundObserver == null) {
throw NullPointerException("boundObserver 为空")
}
val observerWrapperClazz: Class<*> = boundObserver.javaClass.superclass as Class<*>
val mLastVersionField: Field = observerWrapperClazz.getDeclaredField("mLastVersion")
mLastVersionField.isAccessible = true
val mVersionField: Field = liveDataClazz.getDeclaredField("mVersion")
mVersionField.isAccessible = true
val mVersionValue: Any = mVersionField.get(this)!!
mLastVersionField.set(boundObserver, mVersionValue)
}.onFailure {
it.printStackTrace()
}
}
}
}