文章目录
一、分析内容
在 上篇文章 中有了解过 MediatorLiveData 的使用过程,虽然使用的过程很简单,但是却出现了一个又一个的疑问……所以本篇文章就和大家一起来刨根问底,解疑答惑:
- 为什么 MediatorLiveData 需要激活才能够接管 LiveData 的响应事件?
- 怎么激活 MediatorLiveData ?
- 为什么 MediatorLiveData 的
observe()
或者observeForever
的匿名类没有发生回调?
二、为什么 MediatorLiveData 需要激活才能够接管 LiveData 的响应事件?
先请出我们的主角方法 addSource()
:
//为了更好的分析描述,不使用 Lamboda
mediatorLiveData.addSource(originData, object : Observer<String>{
override fun onChanged(it: String?) {
Log.e("==>liveData","addSourceObserver:$it")
}
})
很明显,我们只需要了解 onChanged()
在什么时候会被调用,所以继续查看 addSource()
的源码:
private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
Source<S> e = new Source<>(source, onChanged);
Source<?> existing = mSources.putIfAbsent(source, e);
//无关代码
... ...
}
本来我们是想找找看 onChanged.onChanged(T)
会不会在这里调用,但是我们却发现 源LiveData对象 source
和回调接口 onChanged
被包装到一个 Source 的类中,我们再看看这个类,他是 MediatorLiveData 私有化的静态内部类:
private static class Source<V> implements Observer<V> {
final LiveData<V> mLiveData;
final Observer<? super V> mObserver;
int mVersion = START_VERSION;
Source(LiveData<V> liveData, final Observer<? super V> observer) {
mLiveData = liveData;
mObserver = observer;
}
void plug() {
mLiveData.observeForever(this); //2
}
void unplug() {
mLiveData.removeObserver(this);
}
@Override
public void onChanged(@Nullable V v) {
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
mObserver.onChanged(v); //1
}
}
}
我们先看到构造方法,传入的两个参数分别都赋值给了类的内部属性:mLiveData
和 mObserver
,所以我们找找看,有没有 mObserver.onChanged(T)
这个方法,就在 标记 1 的位置。
但是我们发现这里被一个 Observer<T> 接口的方法 onChanged()
包裹住了,那么这个方法怎么调用呢?
我们直接把目光放到 标记 2 的位置。这个 mLiveData
是什么还记得吗?就是 addSource()
时,传来的被接管的 LiveData 对象。当这行代码被执行,那么 mLiveData
值的变化就会影响到 Source 这个类,那么就会调用 onChanged()
方法,从而才有机会继续调用mObserver.onChanged(T)
。
小结:所以我们需要调用到 void plug()
这个方法,才能够“激活” MediatorLiveData,使得匿名类的 onChanged(T)
方法能够被调用。
那么问题来了:void plug()
这个方法何时会被调用?
三、怎么激活 MediatorLiveData?
我们跟踪 plug()
可以发现有两条路线:
1. 路线一 ——observeForever()
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
... ...
if (hasActiveObservers()) {
e.plug();
}
}
public boolean hasActiveObservers() {
return mActiveCount > 0;
}
void activeStateChanged(boolean newActive) {
... ...
LiveData.this.mActiveCount += mActive ? 1 : -1;
... ...
}
我们一层一层的往下找,发现如果调用 activeStateChanged(true)
的话,就可以达到效果,这个地方又有两个地方被调用到:
//第一个地方
public void observeForever(@NonNull Observer<? super T> observer) {
... ...
wrapper.activeStateChanged(true);
}
//第二个地方(此处先不管)
public void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
所以我们可以通过第一个地方来实现激活 MediatorLiveData 的效果,那就是调用 addSuorce()
之前 调用 observeForever()
即可,但是如果我们把 observeForever()
放在 addSuorce()
之后,一样能够激活…… 这又是为什么呢?
如果我们把 observeForever()
放在 addSuorce()
之后,那么当执行到 addSource()
的时候:
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
... ...
if (hasActiveObservers()) {
e.plug();
}
}
hasActiveObservers()
一定会返回 false,所以不是在这个地方激活的……所以我们继续执行 observeForever()
,这个时候还是会调用到 wrapper.activeStateChanged(true);
:
int mActiveCount = 0;
void activeStateChanged(boolean newActive) {
... ...
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0; //1
LiveData.this.mActiveCount += mActive ? 1 : -1; //2
if (wasInactive && mActive) {
onActive(); //3
}
... ...
}
此时 标记 2 处的 mActiveCount
加个一已经没有任何意义了,因为 hasActiveObservers()
这个判断早就执行并且返回 false 了。
但是我们继续看下去,可以发现能够执行 标记 3 的代码,我们跟踪这个方法:
@Override
protected void onActive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().plug();
}
}
是不是就看到了很熟悉的方法?所以这也是为什么 observeForever()
能够在 addSource()
之后调用,也能够使得 MediatorLiveData 激活了。
2. 路线二——生命周期
我们知道 observeForever()
和 observe()
的区别就是后者多了一个生命周期的管理,所以当我们调用 mediatorLiveData.observe()
之后,就会通过监听生命周期的变化来进行一些操作:
@Override
public void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
是不是又看到了熟悉的方法?不用继续分析,我们通过上一个路线的分析就能够得出 observe()
方法为什么能够激活 MediatorLiveData 了。
四、为什么 MediatorLiveData 的 observe() 或者 observeForever 的匿名类没有发生回调?
MediatorLiveData 对象能够接管一个 LiveData 的变化,且回调发生在 addSource()
方法里面,但是我们得通过 observe()
或者 observeForever ()
方法才能够激活 MediatorLiveData,而这两个方法也有一个回调事件,可是这个回调事件并没有跟随 LiveData 得变化而调用……
解释也很简单:
MediatorLiveData 是继承自 MutableLiveData 的,所以按照基本法,我们需要调用 mediatorLiveData.setValue()/postValue()
才能够收到 observe()/observeForever ()
的回调事件。
五、总结
了解 MediatorLiveData 的源码还是比较重要的,因为有很多骚操作都是要借助这个类来进行的……如果我们了解了该类的源码,那么理解那些骚操作的原理就会非常简单了。