-
簡介
-
LiveData
是androidx.lifecycle-livedata包下的一個抽象類,實現(xiàn)了一種關(guān)聯(lián)了生命周期的簡單觀察者模式,主要的功能就是用于視圖層與數(shù)據(jù)間的單向一對多通知,一個LiveData
會持有一個可觀察的Data對象,一開始是處于NOT_SET
狀態(tài),當用戶通過setValue方法更新后,LiveData
會遍歷所有的observer(處于Active狀態(tài)的),通知他們Data的更新.LiveData
的行為會在Lifecycle
范圍內(nèi),避免很多Activity Leak和空指針
本文代碼樣例都是kotlin,LiveData的源碼是java
-
-
LiveData的使用
//聲明一個LiveData val data:MutableLiveData<String> = MutableLiveData() //在需要的地方訂閱,observer的onChange方法會回調(diào) data.observe(lifecycleOwner,observer) //可以和retrofit配合使用 interface ApiService { @GET("/api/get") fun getChannels():LiveData<ApiResponse<Page<Media>>> } //可以和room配合使用 @Dao interface BorrowModelDao { @Query("select * from s_borrow_moel") fun getAllBorrowedItems(): LiveData<List<BorrowModel>> } //配合ViewModel保存數(shù)據(jù)/監(jiān)聽數(shù)據(jù)更改 class MyViewModel:ViewModel(){ val data:MutableLiveData<String> = MutableLiveData() }
-
LiveData Tricks
- Transformations.map方法轉(zhuǎn)換LiveData的數(shù)據(jù)類型
比如我們用Retrofit獲取了一個User類數(shù)據(jù):LiveData<User>,但是我們只想把User.name暴露給外部觀察者,那么我們可以這樣操作
private val userLiveData:MutableLiveData<User> = MutableLiveData() val userNames:LiveData<String> = Transformations .map(userLiveData){ user -> user.name }
Transformations在androidx.lifecycle包下
- MediatorLiveData
MediatorLiveData可以同時觀察多個LiveData的變化//聲明 val mediatorLiveData:MediatorLiveData<String> = MediatorLiveData() //其他合適的地方添加source mediatorLiveData.addSource(stringFromNetwork){ mediatorLiveData.value = it } mediatorLiveData.addSource(stringFromDatabase){ mediatorLiveData.value = it }
- Transformations.map方法轉(zhuǎn)換LiveData的數(shù)據(jù)類型
-
配合ViewModel使用
- 我們知道
ViewModel
可以在一個LifecycleOwner
的onCreate
到OnDestroy
之間保存實例不受到屏幕旋轉(zhuǎn)等ConfigChange的影響
所以可以通過Activity/Fragment
持有ViewModel
,而ViewModel
持有各類LiveData
,Activity/Fragment
注冊觀察需要的數(shù)據(jù),實現(xiàn)數(shù)據(jù)與UI的同步,而且不會因此發(fā)生Activity
泄漏,甚至可以用ViewModel
來進行Activity/Fragment
之間的通訊
- 我們知道
-
關(guān)于Lifecycle
-
Lifecycle組成
-
LifecycleOwner
:Activity/Fragment
都是LifecycleOwner
(support包下的AppCompatActivity和對應的Fragment),他是androidx.lifecycle:lifecycle-common包下的一個借口,只有g(shù)etLifecycle()一個方法,返回一個Lifecycle對象 -
Lifecycle
: 而這個Lifecycle
就是維護生命周期state的主體,默認實現(xiàn)是LifecycleRegistry
,這個說起來也挺長的,以后有空再新的文章里仔細說明,反正現(xiàn)在讀者只要知道我們常用的AppCompatActivity/Fragment
都是可以拿到生命周期Lifecycle的就行了 -
LifecycleObserver
: 也是一個接口,不過它一個抽象方法也沒有,如果我們需要一個新的自定義的觀察
者,只要實現(xiàn)這個接口,然后在需要對應生命周期方法回調(diào)的方法上添加
OnLifecycleEvent
注解并添加對應注解就好了,LiveData
有一個
LifecycleBoundObserver
內(nèi)部類實現(xiàn)了這個接口,不過繼承關(guān)系是這樣的
LifecycleObserver
<--GenericLifecycleObserver
<-LifecycleBoundObserver
,
LifecycleBoundObserver
會在onStateChange
收到回調(diào),不依賴于注解,不過讀
者現(xiàn)在只要知道在Lifecycle
中state
發(fā)生改變的時候,LifecycleObserver
會收
到通知(void onStateChanged(LifecycleOwner source, Lifecycle.Event event);
)
-
-
-
LiveData類分析
- 簡單的類結(jié)構(gòu)
有幾個內(nèi)部類,都是ObserverWrapper的子類,用于普通的觀察者(帶生命周期)的LifecycleBounderObserver
,和不帶的AlwaysActiveObserver
..
abstract class LiveDate{ class LifecycleBounderObserver extends ObserverWrapper implements GenericLifecycleObserver{ } private abstract ObserverWrapper{ } private class AlwaysActiveObserver extends ObserverWrapper { } }
- 簡單的類結(jié)構(gòu)
-
observe入手分析
- 傳入?yún)?shù):
LifecycleOwner
,Observer
類(簡單的回調(diào)通知接口) - 首先通過
LifecycleOwner
獲取Lifecycle
,判斷時候是DESTROYED
狀態(tài),是的話直接return
將Observer
和LifecycleOwner
包裝為LifecycleBoundObserver
對象 - LiveData維護了一個
SafeIterableMap<Observer<? super T>, ObserverWrapper>
對象mObservers,保存了Observer和對應的Wrapper,存入LifecycleBoundObserver對象后判斷是否已存在并且是否對應當前LifecycleOwner,做出相應的處理,當mObservers中沒有時,直接給LifecycleOwner的Lifecycle注冊該LifecycleBoundObserver - 所以說實際上是我們傳入的LifecycleOwner保存的Lifecycle注冊了一個觀察者,LifecycleBoundObserver會在state 等于 DESTROYED的時候移除該觀察者,在其他狀態(tài)的時候調(diào)用activeStateChange()方法
- 先比較當前mActive和新active,賦值給
mActive
,然后通過LiveData類的mActivieCount是否為0來判斷是不是完全沒有通知過,如果是進入非active狀態(tài)mActiveCount就-1,否則+1,原先未active現(xiàn)在active了,調(diào)用onActive
方法,新的mActivieCount == 0
并且 新active的狀態(tài)為false就調(diào)用onInactive
方法,然后判斷mActive
,true則會調(diào)用dispatchValue方法,基本上mActivieCount只會有0 -> 1 ,1 -> 0兩個狀態(tài)變化,所以onActive
是LiveData觀察者數(shù)量從無到有時回調(diào),onInactive
反之private abstract class ObserverWrapper { final Observer<? super T> mObserver; boolean mActive; int mLastVersion = START_VERSION; 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); } }
- 傳入?yún)?shù):
}
```
- 上面羅里吧嗦一大推讀者可能一臉懵逼,反正結(jié)論就是,LiveData狀態(tài)由沒有觀察者到有觀察者會走
onActive
方法,反之會走onInactive
方法,不管原先狀態(tài)如何,只要新狀態(tài)是活躍就會走dispatchValue
-
onInactive/onActive
是LiveData
里兩個open protected的方法,只在MediatorLiveData里有實現(xiàn),我還沒有仔細研究MediatorLiveData,大家可以去看看源碼 - 所以LifecycleBoundObserver新狀態(tài)為活躍時,會調(diào)用外部類
LiveData
的dispatchValue
方法,傳入的參數(shù)為ObserverWrapper
,也就是LifecycleBoundObserver的父類(LifecycleBoundObserver
繼承了ObserverWrapper
,實現(xiàn)了GenericLifecycleObserver
),在這要注意下內(nèi)部類(非靜態(tài))是可以拿到外部類實例的,LiveData.this.XXX,忘記的同學復習下,我是好久沒用java,突然看到有點懵逼..
//傳入?yún)?shù)是Observer,有的話就分發(fā)給它,為null就對所有Observers分發(fā)數(shù)據(jù)
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//如果正在分發(fā)數(shù)據(jù),就標記為分發(fā)無效,分發(fā)中的會因此跳出循環(huán)
if (mDispatchingValue) {
//標記為分發(fā)無效
mDispatchInvalidated = true;
return;
}
//標記為分發(fā)中
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(); ) {
//嘗試分發(fā)
considerNotify(iterator.next().getValue());
//標記為無效時會跳出循環(huán),在while循環(huán)中等待一次mDispatchInvalidated再次變?yōu)閠rue時再次進入for循環(huán)
if (mDispatchInvalidated) {
break;
}
}
}
//沒有被標記無效時while循環(huán)就執(zhí)行一次完事,否則會再次執(zhí)行
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
-
LiveData
中的mDispatchingValue/mDispatchInvalidated
在此處保證不會重復分發(fā)或者分發(fā)舊的value,當setValue
分發(fā)調(diào)用dispatchValue(null)
時會遍歷所有的Observer分發(fā)新值,否則只分發(fā)給傳入的ObserverWrapper
,這里說明下:LiveData
維護了mDispatchingValue/mDispatchInvalidated
,而Observer可能會有多個,都持有LiveData對象(因為是內(nèi)部類),所以等待的observer對應的LiveData
會獲得mDispatchInvalidated = true
,中斷進行中的分發(fā),讓舊數(shù)據(jù)不再分發(fā) -
considerNotify
: 第一步檢查ObserverWrapper
是否mActive
,第二步檢查shouldBeActive()
,第三步檢查ObserverWrapper
的版本observer.mLastVersion >= mVersion
,最后才通知更新,調(diào)用Observer的onChange方法 - ObserverWrapper中的mLastVersion /和LiveData的mVersion用來防止再入活躍狀態(tài)后重復分發(fā)
-
ObserverWrapper
中的mActive
用來控制該觀察者是否需要分發(fā)(activeStateChanged(boolean)
方法的作用下) -
considerNotify方法
先上代碼
很簡單的邏輯,就是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; //noinspection unchecked observer.mObserver.onChanged((T) mData); }
- 第一步判斷是否active,這個mActive屬性在幾種情況下會為true
a. Observer是通過observeForever注冊的
b. Observer的shouldBeActive返回true
我們看看方法代碼,只有綁定的Lifecycle的State大于STARTED才會為true
- 第一步判斷是否active,這個mActive屬性在幾種情況下會為true
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
mActive會在生命周期變化時會被多次檢查
2. 第二步再次檢查`shouldBeActive()`狀態(tài)
3. 第三步檢查`mLastVersion`和`mVersion`
這個version是在setValue時被+1的,檢查一下防止重復分發(fā),完成后修改lastVersion然后回調(diào)`onChange(T)`
-
setValue/postValue方法的分析
按慣例先看看代碼,postValue的代碼也好理解,只是給賦值操作加了一個鎖,并把setValue放到主線程執(zhí)行,使多個postValue只有最后一個的value生效
private final Runnable mPostValueRunnable = new Runnable() { @Override public void run() { Object newValue; synchronized (mDataLock) { newValue = mPendingData; mPendingData = NOT_SET; } //noinspection unchecked 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) { assertMainThread("setValue"); mVersion++; mData = value; dispatchingValue(null); }
想象一下如果兩個線程
T-A
,T-B
里都執(zhí)行了postValue傳入不同的值A(chǔ),B,先會在方法內(nèi)的mDataLock鎖住的代碼塊競爭執(zhí)行,比如A先執(zhí)行,mPendingData
先被賦值為A,postTask
=> true,然后賦值為B,也就是說第一次的賦值才會通過同步塊之后的if判斷,執(zhí)行分發(fā)runnable,線程T-B
只是修改了mPendingValue
的值然后會有一個主線程上的同步代碼塊(也是同一個鎖),將新值執(zhí)行
setValue
,mPendingValue
重設為初始值,也就是說取得值實際上是后一個線程的B,后面分發(fā)完成重設為NOT_SET
,后面的PostValue又進入原來的邏輯了postValue的注釋也很清楚了: If you called this method multiple times before a main thread executed a posted task, only
the last value would be dispatched. -
基本流程
- observe() -> 新建Observer -> Observer的StateChange -> dispatchValue -> considerNotify
- setValue/postValue -> dispatchValue -> considerNotify
-
總結(jié)
LiveData的結(jié)構(gòu)是比較簡單的,使用時注意不要多次注冊觀察者,一般如果在Activity中使用,就在OnCreate方法注冊,Activity被關(guān)閉或回收后觀察者會自動解除訂閱,所以不會發(fā)生泄漏,我們也可以自己繼承LiveData做更多的定制來實現(xiàn)自己的業(yè)務邏輯,配合Tranformations工具類和MediatorLiveData可以實現(xiàn)很多比較復雜的邏輯