一般来说,这种观察者模式都是先订阅,后收到消息。但是 LiveData 有粘性效果,就是我先改变数据,后订阅,但是还能收到之前修改(只保存一个,就是最后那个数据的粘性)的数据。
LiveData 就是利用 Lifecycle ,它的 Observer 是 如果发现状态是 DESTROY 状态,就会 remove 掉这个 Observer 观察者,所以我们在代码种都是 MyLiveData.info1.observe(this, MyObserver()) 添加 Observer ,但是并没有反注册移除 Observer 的操作,就是因为在 DESTROY 的时候,它自己会移除。首先来看 LiveData 的使用:
1 2 3 4 5 6 7 8 9 10 11 object MyLiveData { val info1: MutableLiveData<String> by lazy { MutableLiveData() } } MyLiveData.info1.observe(this , object : Observer<String> { override fun onChanged (t: String ?) { } })
我们可以定义一个 MutableLiveData ,然后去 observe 它,当上面的 info1 有改变时,下面的 onChanged() 方法就会调用。看下 observe 的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @MainThread public void observe (@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) { assertMainThread("observe" ); if (owner.getLifecycle().getCurrentState() == DESTROYED) { 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); }
首先,observe 操作必须在主线程调用 ,否则会报错。其次,会将传入的 observer 保存在 Map 中,最后,将封装的 LifecycleObserver 添加到 Lifecycle 的监听中去。到这里貌似没有可以继续分析的代码了,我们来看值的改变,因为值的改变会触发传入的 observer ,有 postValue 和 setValue 两种方法:
1 2 MyLiveData.info1.value = "初始化" MyLiveData.info1.postValue("开始啦" )
其实, postValue 最终也是使用 setValue 实现的:
1 2 3 4 5 6 7 8 9 10 11 protected void postValue (T value) { boolean postTask; synchronized (mDataLock) { postTask = mPendingData == NOT_SET; mPendingData = value; } if (!postTask) { return ; } ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); }
首先经过线程同步,最后将操作 post 到主线程操作。这个 runnable 就是调用 setValue 的操作:
1 2 3 4 5 6 7 8 9 10 11 12 private final Runnable mPostValueRunnable = new Runnable() { @SuppressWarnings("unchecked") @Override public void run () { Object newValue; synchronized (mDataLock) { newValue = mPendingData; mPendingData = NOT_SET; } setValue((T) newValue); } };
所以,我们可以猜测,setValue 应该是要在主线程调用的,使用 postValue 也是为了在子线程中调用能够 setValue :
1 2 3 4 5 6 protected void setValue (T value) { assertMainThread("setValue" ); mVersion++; mData = value; dispatchingValue(null ); }
从代码可以看出,setValue 确实需要在主线程调用,并且,每次调用之后,就会 mVersion ++ ,在 setValue 之后,可以看到调用了 dispatchingValue 将这个 value 值分发给观察者了:
1 2 3 4 5 6 7 8 9 10 11 void dispatchingValue (@Nullable ObserverWrapper initiator) { for (Iterator< Map.Entry < Observer < ? super T >, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); if (mDispatchInvalidated) { break ; } } }
省略了其他代码,可以看到,不断从 mObservers 中(Map 类型,就是前面 observe 的时候,将 Observer 保存到的那个 Map)取出元素去做 considerNotify 操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private void considerNotify (ObserverWrapper observer) { if (!observer.mActive) { return ; } if (!observer.shouldBeActive()) { observer.activeStateChanged(false ); return ; } if (observer.mLastVersion >= mVersion) { return ; } observer.mLastVersion = mVersion; observer.mObserver.onChanged((T) mData); }
所以,LiveData 中有很多 Active 的判断,其中下面的判断:
1 2 3 if (observer.mLastVersion >= mVersion) { return ; }
这个地方决定了消息的粘性,也就是通过版本号来决定粘性,其实判断的就是是 setValue/postValue 和 observe 的先后关系 ,如果我们通过反射让他们的值相等,即: observer.mLastVersion == mVersion ,这样就会执行里面的 return ,if 后面的语句将不会执行,也就不会有粘性了(在订阅行为发生以前的改动都不会发送过来)。
另外,我们看到,当生命周期状态改变时,就会调用 onStateChanged :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @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(); } }
从这里可以知道,当 状态变为 DESTROYED 的时候,就会执行 removeObserver(mObserver); 移除 Observer 的操作,所以,我们才不需要手动去 remove 。