本文是深刻理解「Android Architecture Components」系列文章第三篇 源碼基於 android.arch.lifecycle:livedata-core:1.1.1html
【AAC 系列一】Android 應用架構新時代來臨!java
【AAC 系列二】深刻理解架構組件的基石:Lifecyclereact
【AAC 系列三】深刻理解架構組件:LiveDataandroid
這個連接不要點,千萬不要git
在以前咱們深刻研究了 Lifecycle 的實現原理,並在文末提到了LiveData 以及 ViewModel,此次咱們來說講 LiveData。github
LiveData 是 Android Architecture Components 中的一員,先看下官方是如何介紹的:數據庫
LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state. [見 9.1]緩存
This class is designed to hold individual data fields of ViewModel, but can also be used for sharing data between different modules in your application in a decoupled fashion. [見 9.2]網絡
簡單講 LiveData 是一個可以感知生命週期、可觀察的數據持有類
,它被設計成 ViewModel 的一個成員變量;能夠以一個 更解耦
的方式來共享數據。架構
實際使用下來發現 LiveData 有幾個特性:
Active
狀態(STARTED/RESUMED)下通知數據改變;那麼 LiveData 上述特性的原理是怎麼樣的呢?
使用 LiveData 又須要注意些什麼呢?
本文將圍繞此展開。
雖然 LiveData 一般跟 ViewModel 配合使用,不過也能夠單獨使用,爲了簡單起見,這裏不配合 ViewModel。
如下是一個簡單的例子:
MutableLiveData<String> liveString = new MutableLiveData<>();
liveString.observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable final String s) {
Log.d(TAG, "onChanged() called with: s = [" + s + "]");
}
});
liveString.postValue("程序亦非猿");
複製代碼
運行後能夠看到日誌輸出:onChanged() called with: s = [程序亦非猿]
。
釋義:
定義一個 MutableLiveData (LiveData 的一個經常使用子類),經過 observe 方法能夠訂閱修改數據的通知,經過 postValue()
或者 setValue()
方法能夠更新數據,已經訂閱的 Observer 可以獲得數據更改的通知,也即回調 onChanged()
方法。
這樣就算是用上 LiveData 了。
接下來,上乾貨!
在分析原理前,再明確一下咱們的疑問:
同時提早看下我整理的 LiveData UML 圖,對 LiveData 有個總體的瞭解,後續的涉及到的類都在這裏了,有助於理解。
OK, here we go!
LiveData 的使用流程從 observe()
開始,我們嘗試從 observe()
方法 開始分析:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
//若是是 DESTROYED 的狀態則忽略
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//把 Observer 用 LifecycleBoundObserver 包裝起來
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//緩存起來
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//若是已經 observe 過 而且兩次的 owner 不一樣則報錯
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//綁定 owner
owner.getLifecycle().addObserver(wrapper);
}
複製代碼
能夠看到 observe 方法裏把咱們傳遞的 observer 用 LifecycleBoundObserver
包裝了起來,而且存入了 mObservers
,而且跟 owner 進行了關聯。
而且作了兩個特殊處理:
這裏出現了幾個新的類 LifecycleBoundObserver 、ObserverWrapper 來看看。
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
// 判斷 owner 當前的狀態是不是至少 STARTED
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//生命週期改變,若是是 DESTROYED 就自動解除
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
//ObserverWrapper.activeStateChanged
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
複製代碼
**ObserverWrapper **:
private abstract class ObserverWrapper {
final Observer<T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<T> observer) {
mObserver = observer;
}
//是不是 active 狀態
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return 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) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
//若是 active 狀態下,則發送數據更新通知
if (mActive) {
dispatchingValue(this);
}
}
}
複製代碼
仔細看下這兩個類其實就能解答疑問了。
LifecycleBoundObserver 是 抽象類 ObserverWrapper 的子類,重寫了 shouldBeActive() 方法,在 owner 處於至少是 STARTED 的狀態下認爲是 active 狀態;而且它也實現了 GenericLifecycleObserver 接口,能夠監聽 lifecycle 回調,而且在 onStateChanged() 方法裏處理了生命週期改變的事件,當接收到 DESTROYED 的事件會自動解除跟 owner 的綁定,而且將下個流程交給了 activeStateChanged() 。
到這裏 【2.1】、【2.3】的問題已經有了答案:
【2.1】答:LifeData 在 observe 方法中用 LifecycleBoundObserver 包裝了 observer ,而且經過它綁定了owner。
【2.3】答:LifecycleBoundObserver 在 onStateChanged() 方法裏處理了生命週期改變的事件,當接收到 DESTROYED 的事件會自動解除跟 owner 的綁定。
這裏須要注意的是,當咱們調用 observe() 註冊後,因爲綁定了 owner,因此在 active 的狀況下,LiveData 若是有數據,則 Observer 會立馬接受到該數據修改的通知。
此時的流程是:
observe-->
onStateChanged-->
activeStateChanged-->
dispatchingValue-->
considerNotify-->
onChanged
能夠稱之爲生命週期改變觸發的流程,另外還有一種流程是 postValue&setValue 觸發的流程,共兩種。
在 activeStateChanged() 方法裏,處理了 onActive() 跟 onInactive() 回調的相關邏輯處理,而且調用了dispatchingValue(this) 。(MediatorLiveData 用到了 onActive() 跟 onInactive() 有興趣自行了解,這裏不展開)
接下去探索 dispatchingValue
。
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
//若是正在分發則直接返回
if (mDispatchingValue) {
//標記分發失效
mDispatchInvalidated = true;
return;
}
//標記分發開始
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//生命週期改變調用的方法 initiator 不爲 null
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//postValue/setValue 方法調用 傳遞的 initiator 爲 null
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
//標記分發結束
mDispatchingValue = false;
}
複製代碼
considerNotify(ObserverWrapper)
方法:
private void considerNotify(ObserverWrapper observer) {
//檢查狀態 確保不會分發給 inactive 的 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;
}
//setValue 會增長 version ,初始 version 爲-1
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
複製代碼
能夠看到 dispatchingValue 正是分發事件邏輯的處理方法,而 considerNotify 方法則確保了只將最新的數據分發給 active 狀態下的 Observer 。
另外也能夠看到 LiveData 引入了版本管理來管理數據 (mData)以確保發送的數據老是最新的。(具體很少講)
dispatchingValue 這裏分兩種狀況:
須要着重講一下。
上面提到過,LifecycleBoundObserver.onStateChanged 方法裏調用了 activeStateChanged ,而該方法調用dispatchingValue(this);傳入了 this ,也就是 LifecycleBoundObserver ,這時候不爲 null 。
也就是說生命週期改變觸發的流程就是這種狀況,這種狀況下,只會通知跟該 Owner 綁定的 Observer。
上面我也提早說了,除了生命週期改變觸發的流程外,還有 postValue&setValue 流程,來看下這倆方法。
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
//調用 setValue
setValue((T) newValue);
}
};
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
@MainThread
protected void setValue(T value) {
//必須在主線程調用 不然會 crash
assertMainThread("setValue");
mVersion++;//增長版本號
mData = value;
//傳入了 null
dispatchingValue(null);
}
複製代碼
LiveData 的 postValue 方法其實就是把操做 post 到主線程,最後調用的仍是 setValue 方法,注意 setValue 必須是在主線程調用。
而且能夠看到** setValue 方法調用了 dispatchingValue 方法,並傳入了 null ,這個時候的流程則會通知 active 的mObservers**。
到這裏以前的剩下的全部疑問也均可以解答了。
LiveData 的兩個流程都會走到 dispatchingValue 處理分發通知邏輯,而且在分發通知前會判斷 owner 的狀態,再加上 LiveData 自己內部的版本管理,確保了只會發送最新的數據給 active 狀態下的 Observer。
**注意:**LiveData 對同時屢次修改數據作了處理,若是同時屢次修改,只會修改成最新的數據。
再看一遍類圖,回顧一下:
Lifecycle 改變觸發流程:
Lifecycle postValue/setValue 觸發流程:
LiveData 還有不少其餘相關知識,這裏列舉一些,更多實踐能夠看一下【7.6】。
LiveData 被訂閱時,若是以前已經更改過數據,而且當前 owner 爲 active 的狀態,activeStateChanged() 會被調用,也即會立馬通知到 Observer ,這樣其實就相似 EventBus 的 sticky event 的功能,須要注意的是,不少時候咱們並不須要該功能。具體能夠看一下【7.6】的處理。
默認狀況下,LiveData 會跟 LicycleOwner 綁定,只在 active 狀態下更新,如若想要無論在什麼狀態下都能接收到數據的更改通知的話,怎麼辦?這時候須要使用 AlwaysActiveObserver ,改調用 observe 方法爲調用 LiveData.observeForever(Observer) 方法便可。
LiveData 還有一個子類是 MediatorLiveData,它容許咱們合併多個 LiveData,任何一個 LiveData 有更新就會發送通知。好比咱們的數據來源有兩個,一個數據庫一個網絡,這時候咱們會有兩個 DataSource,也就是兩個 LiveData,這個時候咱們可使用 MediatorLiveData 來 merge 這兩個 LiveData。
Transformations 容許咱們把一個 LiveData 進行處理,變化成另一個 LiveData,目前支持 map 跟 switchMap 兩個方法,跟 RxJava 的操做相似。
好比,用 map 把一個 String 類型的 LiveData 轉換成 Integer 類型:
Transformations.map(liveString, new Function<String, Integer>() {
@Override
public Integer apply(final String input) {
return Integer.valueOf(input);
}
}).observe(this, new Observer<Integer>() {
@Override
public void onChanged(@Nullable final Integer integer) {
}
});
複製代碼
EventBus 基於觀察者模式,LiveData 也是,因此 LiveData 能夠被用來作成 LiveDataBus,有興趣能夠搜索。
observeForever()
方法;LiveData 基於觀察者模式,而且能夠感知生命週期,這使得咱們使用 LiveData 既能夠享受觀察者模式帶來的隔離數據與 UI 等強大的解耦能力,還能夠享受感知生命週期帶來的巨大便利。而且還無需擔憂內存泄露這個使人頭疼的問題。
咱們可使用 LiveData 很是輕鬆地作到一些很是高效的操做,如僅在 active 的狀態下刷新 UI,能夠避免沒必要要的數據刷新。
顯而易見 LiveData 自己的優秀特性有着巨大的價值,利用好絕對是架構設計中的一大利器,另外 LiveData 配合 ViewModel 能夠發揮更大的價值,機智的你必定已經知道下一篇文章講什麼了。