LiveData的主要工作:
一個帶有生命周期偵測特性的數(shù)據(jù)持有者。
AAC架構(gòu)中的實(shí)際數(shù)據(jù)持有者搁骑,通常存放在ViewModel
中,通過ViewModel
脫離生命周期對數(shù)據(jù)的影響又固。
本身機(jī)制是觀察者模式仲器,在數(shù)據(jù)更新時,會通知所有已激活 (或根據(jù)需求通知未激活) 的觀察者最新數(shù)據(jù)仰冠。
由于生命周期偵測的特性乏冀,LiveData
在添加觀察者時,要求觀察者附帶其生命周期所在的LifecycleOwner
洋只。
LiveData的主要類:
LiveData
核心功能類辆沦,抽象類昼捍。
LiveData
模塊的主體,模塊的基本實(shí)現(xiàn)都在該類中肢扯。MutableLiveData
核心功能類妒茬。
是LiveData
的非抽象子類,只是把postValue()
和setValue()
的訪問權(quán)限擴(kuò)大成public
并可實(shí)例化蔚晨。Observer
核心功能類郊闯,觀察者接口。LiveData$ObserverWrapper
LiveData
的內(nèi)部類蛛株,觀察者實(shí)例的容器類的抽象父類团赁。
注冊到LiveData
的觀察者,被會ObserverWrapper
的子類包裝谨履,再加入觀察者列表欢摄。
維護(hù)了對應(yīng)觀察者的:
1- 當(dāng)前數(shù)據(jù)版本
2- 當(dāng)前觀察者的激活狀態(tài)
同時負(fù)責(zé)通知LiveData
的onActive()
和onInactive()
。LiveData$AlwaysActiveObserver
ObserverWrapper
的一個子類笋粟。
通過LiveData.observeForever()
傳入的觀察者將會被此類包裝怀挠。
被該類包裝的觀察者不關(guān)注生命周期,不受生命周期影響害捕,并且激活狀態(tài)永久為true
绿淋。
使用該方法時應(yīng)該注意手動釋放觀察者,以避免內(nèi)存泄漏尝盼。LiveData$LifecycleBoundObserver
核心功能類吞滞,ObserverWrapper
的一個子類。
通過LiveData.observe()
傳入的觀察者將會被此類包裝盾沫。
該類是LiveData
生命周期監(jiān)管的核心裁赠,該類實(shí)現(xiàn)了LifecycleEventObserver
接口,并在創(chuàng)建后注冊到觀察者對應(yīng)的生命周期內(nèi)赴精,以實(shí)現(xiàn)激活狀態(tài)管理和主動釋放佩捞。MediatorLiveData
MutableLiveData
的一個子類。
該類除了LiveData
的功能外蕾哟,允許對多個LiveData
的進(jìn)行觀察一忱。
簡單的描述:
MutableLiveData
會把需要觀察的LiveData
和對應(yīng)的Observer
封裝為一個Source
,自身則維護(hù)著Source
列表谭确。
當(dāng)MutableLiveData
激活時帘营,遍歷Source
列表,以AlwaysActiveObserver
的形式對需要觀察的LiveData
進(jìn)行注冊琼富。
而MutableLiveData
失去激活時仪吧,則自動移除Source
列表中所有LiveData
注冊。
任意LiveData
數(shù)據(jù)更新時鞠眉,根據(jù)需求薯鼠,決定是否對自身進(jìn)行維護(hù)或更新,即實(shí)現(xiàn)了對任意個LiveData
的數(shù)據(jù)更新事件進(jìn)行管理械蹋。Transformations
工具類出皇,不可實(shí)例化。
用于實(shí)現(xiàn)LiveData
的數(shù)據(jù)進(jìn)行一定的流處理操作哗戈,例如發(fā)布控制郊艘,類型轉(zhuǎn)換等。
工具類的方法唯咬,實(shí)際上是通過MediatorLiveData
對傳入的LiveData
進(jìn)行觀察纱注,當(dāng)LiveData
更新數(shù)據(jù)時,數(shù)據(jù)會傳入的用戶定義的方法中進(jìn)行控制或轉(zhuǎn)換胆胰,然后選擇性通過MediatorLiveData.setValue()
發(fā)布處理后的數(shù)據(jù)狞贱。
工具提供了3個方法:(livedata-2.2.0)
1-map
:
使LiveData<X>
通過Function
轉(zhuǎn)換為LiveData<Y>
。
即:LiveData<X>
數(shù)據(jù)更新 - >Function
轉(zhuǎn)換 ->MediatorLiveData<Y>
數(shù)據(jù)更新
..
2-switchMap
:
根據(jù)LiveData<X>
的數(shù)據(jù)蜀涨,根據(jù)Function
返回需要觀察的LiveData<Y>
瞎嬉。
即:LiveData<X>
數(shù)據(jù)更新 - >Function
選擇數(shù)據(jù)源 ->MediatorLiveData<Y>
的數(shù)據(jù)源更新。
..
和map
對比厚柳,map
的數(shù)據(jù)源直接來自LiveData<X>
氧枣;
而switchMap
的數(shù)據(jù)源是Function
返回的LiveData<Y>
,LiveData<X>
對于switchMap
來說只是個數(shù)據(jù)源控制器别垮。
..
3-distinctUntilChanged
屏蔽LiveData<X>
的重復(fù)數(shù)據(jù)發(fā)射便监。
即:LiveData<X>
的setValue
被調(diào)用后,將會檢測數(shù)據(jù)是否變更 ( 通過equals()
) 碳想,未發(fā)生變更時茬贵,將會屏蔽本次更新。ComputableLiveData
一個未公開的類移袍。(livedata-2.2.0)
并非LiveData
的子類解藻,而是內(nèi)部維護(hù)了一個LiveData
。
該類內(nèi)部LiveData
的數(shù)據(jù)來源葡盗,并不來自數(shù)據(jù)的設(shè)置螟左,而是來自子類實(shí)現(xiàn)的compute()
方法的返回值。當(dāng)數(shù)據(jù)更新時觅够,調(diào)用invalidate()
方法通知LiveData
重新調(diào)用compute()
計(jì)算數(shù)據(jù)胶背。默認(rèn)運(yùn)行在一個大小為4,專用IO操作的線程池(arch_disk_io_%i
)喘先。
LiveData的基本使用
- 一般使用:
class VM : ViewModel() {
val dataSource = MutableLiveData<String>()
}
fun simple(vmOwner: ViewModelStoreOwner, lcOwner: LifecycleOwner) {
val vm = ViewModelProvider(vmOwner).get(VM::class.java)
vm.dataSource.observe(lcOwner, Observer { })
}
- 合并觀察:
class VM : ViewModel() {
val intSource = MutableLiveData<Int>()
val dataSource = MutableLiveData<String>()
}
fun simple(vmOwner: ViewModelStoreOwner, lcOwner: LifecycleOwner) {
val vm = ViewModelProvider(vmOwner).get(VM::class.java)
mediator.addSource(vm.intSource) { mediator.value = it.toString() }
mediator.addSource(vm.dataSource) { mediator.value = it }
}
- 類型裝換:
fun simple() {
val source: LiveData<Int> = MutableLiveData<Int>()
val transfor: LiveData<String> = Transformations.map(source) {
it.toString()
}
}
- 數(shù)據(jù)源控制
class VMCtrl : ViewModel() {
private val stateSource = MutableLiveData<Int>()
private val dataSource1 = MutableLiveData<String>()
private val dataSource2 = MutableLiveData<String>()
// stateSource 數(shù)據(jù)變更時會導(dǎo)致 outputSource 的數(shù)據(jù)源變更
// 從而使 outputSource 數(shù)據(jù)發(fā)生變更
val outputSource = Transformations.switchMap(stateSource) {
if (it > 0) {
dataSource1
} else {
dataSource2
}
}
}
- 重復(fù)事件屏蔽
class VMUntilChanged : ViewModel() {
private val source = MutableLiveData<Int>()
// source 設(shè)置同一數(shù)值钳吟,無論多少次,outputSource 只會觸發(fā)一次數(shù)據(jù)更新
val outputSource = Transformations.distinctUntilChanged(stateSource)
}
單次事件發(fā)射:
android/architecture-samples - SingleLiveEvent.java事件總線:
深入理解AAC架構(gòu) - LiveDataBus 基于LiveData實(shí)現(xiàn)的事件總線
LiveData的關(guān)鍵源碼分析
-
LiveData
的源碼并不復(fù)雜窘拯,先從構(gòu)造方法進(jìn)行分析:
在構(gòu)造方法中就可以直接看到LiveData
的兩個關(guān)鍵成員
1- mData
:當(dāng)前LiveData
保存的數(shù)據(jù)红且。
2- mVersion
:當(dāng)前mData
的版本坝茎,默認(rèn)-1,通過設(shè)置數(shù)據(jù)的構(gòu)造方法實(shí)例化時暇番,版本為0嗤放。
static final Object NOT_SET = new Object();
static final int START_VERSION = -1;
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
public LiveData(T value) {
mData = value;
mVersion = START_VERSION + 1;
}
- 從
LiveData.observe()
作為入口分析:
-
mObservers
:
LiveData
的觀察者列表,可以看到實(shí)際對象是ObserverWrapper
類型壁酬,即所有傳入的observer
都會被ObserverWrapper
及其子類封裝次酌。 -
assertMainThread()
:
該處將會檢測是否在主線程調(diào)用,否則拋出異常舆乔。 -
LifecycleBoundObserver
:
ObserverWrapper
子類岳服,觀察者的生命周期管理在此處實(shí)現(xiàn)。 -
existing.isAttachedTo(owner)
:
觀察者不允許綁定多個生命周期希俩,否則拋出異常吊宋。
同一個LiveData
中,觀察者不能同時 持有 / 忽略 生命周期特性斜纪,兩者互斥贫母。 -
addObserver(wrapper)
:
將LifecycleBoundObserver
加入對應(yīng)生命周期回調(diào)以實(shí)現(xiàn)自動生命周期管理
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
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);
}
- 在分析
LifecycleBoundObserver
前,先對其父類ObserverWrapper
進(jìn)行分析:
-
mObserver
:
在構(gòu)造方法中傳入的觀察者實(shí)體盒刚,即用戶構(gòu)建的觀察者腺劣。 -
mActive
:
當(dāng)前觀察者的激活狀態(tài),非激活狀態(tài)時將不會觸發(fā)觀察者的回調(diào)因块。 -
mLastVersion
:
當(dāng)前觀察者對應(yīng)的數(shù)據(jù)版本橘原。 -
shouldBeActive()
:
判斷觀察者是否需要激活,由子類實(shí)現(xiàn)涡上。 -
isAttachedTo()
:
判斷觀察者是否綁定了生命周期趾断,由子類實(shí)現(xiàn),默認(rèn)為false
吩愧。 -
detachObserver()
:
觀察者從LiveData
移除時芋酌,LiveData
會調(diào)用觀察者包裝對象的該方法,以處理必要的釋放操作雁佳。 -
activeStateChanged()
:
觀察者的激活狀態(tài)通過該方法作出改變脐帝。
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
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);
}
}
}
- 其中第
7
點(diǎn)activeStateChanged()
在狀態(tài)改變時,有如下性質(zhì):
-
LiveData
沒有任何已激活的觀察者糖权,且此觀察者激活堵腹,會回調(diào)LiveData
的onActive()
方法。 - 此觀察者取消激活后星澳,
LiveData
沒有任何已激活的觀察者疚顷,會回調(diào)LiveData
的onInactive()
方法。 - 觀察者激活時,會通過
dispatchingValue()
通知LiveData
嘗試派發(fā)數(shù)據(jù)到觀察者腿堤。
- 關(guān)鍵方法
dispatchingValue()
:
該方法實(shí)際上LiveData
對mObservers
列表遍歷進(jìn)行通知嘗試的方法阀坏。
當(dāng)指定觀察者時,嘗試對該觀察者派發(fā)數(shù)據(jù)释液;當(dāng)未指定具體的觀察者時全释,將會遍歷整個mObservers
列表装处,對所有觀察者派發(fā)數(shù)據(jù)误债。
-
dispatchingValue()
的具體的流程:
當(dāng)前正在執(zhí)行派發(fā)時,標(biāo)記當(dāng)次派發(fā)失效妄迁,在while
循環(huán)處重新派發(fā)寝蹈;
指定派發(fā)目標(biāo)時,只對該目標(biāo)進(jìn)行派發(fā)登淘;
未指定派發(fā)目標(biāo)時箫老,遍歷mObservers
,對所有觀察者進(jìn)行派發(fā)黔州,派發(fā)期間檢查失效標(biāo)記耍鬓,失效時,跳出當(dāng)次遍歷流妻,在while
循環(huán)處重新派發(fā)牲蜀。
-
mDispatchingValue
:用于標(biāo)記是否真正派發(fā)數(shù)據(jù)。 -
mDispatchInvalidated
:用于標(biāo)記當(dāng)前派發(fā)是否失效绅这。 considerNotify()
:觀察者在該方法中根據(jù)條件判斷是否進(jìn)行派分?jǐn)?shù)據(jù)涣达。
private boolean mDispatchingValue;
private boolean mDispatchInvalidated;
void dispatchingValue(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;
}
- 實(shí)際的派發(fā)方法
considerNotify()
:
該方法比較簡單,主要是就是對觀察者進(jìn)行激活和版本校驗(yàn)证薇。
通過校驗(yàn)后度苔,記錄最新版本,并推送最新數(shù)據(jù)到觀察者浑度。
-
!observer.mActive
:當(dāng)觀察者未激活時寇窑,不執(zhí)行派發(fā)。 -
observer.shouldBeActive()
:重復(fù)檢查觀察者是否應(yīng)該處于激活狀態(tài)箩张,檢查失敗則通知觀察者取消激活甩骏。 -
observer.mLastVersion >= mVersion
:對比觀察者版本,僅在版本低于LiveData
版本時伏钠,通知觀察者更新横漏。
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);
}
- 以上即可知道整個派發(fā)流程,即通過
dispatchingValue()
發(fā)起熟掂,considerNotify()
校驗(yàn)缎浇,最終派發(fā)到觀察者。
- 回頭分析
LifecycleBoundObserver
:
前文提到赴肚,LifecycleBoundObserver
在LiveData.observe()
時素跺,即綁定到觀察者所指定的生命周期中二蓝,而綁定通過owner.getLifecycle().addObserver()
傳入自身作為對象,即LifecycleBoundObserver
必然實(shí)現(xiàn)LifecycleObserver
指厌。
-
mOwner
:在構(gòu)造方法中要求傳入生命周期對象刊愚。 -
shouldBeActive()
:當(dāng)處于生命周期處于Start - Stop之間時,觀察者激活踩验。 -
onStateChanged()
:生命周期回調(diào)鸥诽。
非Destory狀態(tài),通過activeStateChanged(shouldBeActive())
進(jìn)行自我狀態(tài)校驗(yàn)和處理箕憾。
當(dāng)處于Destory時牡借,通知LiveData
移除觀察者,LiveData
會把包裝類從mObservers
列表中移除袭异,且觸發(fā)其detachObserver()
方法钠龙。 -
isAttachedTo()
:直接判斷生命周期對象是否相同。 -
detachObserver()
:將自身從生命周期中移除御铃,完成整個解綁過程碴里。
class LifecycleBoundObserver
extends ObserverWrapper
implements LifecycleEventObserver {
final LifecycleOwner mOwner;
LifecycleBoundObserver(LifecycleOwner owner, Observer observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle()
.getCurrentState()
.isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
- 通過
LifecycleBoundObserver
,即LiveData.observe()
加入的觀察者上真,實(shí)現(xiàn)了生命周期偵測咬腋,完成激活狀態(tài)管理和自動解綁操作。
- 數(shù)據(jù)更新:
數(shù)據(jù)更新有2個方法谷羞,且都比較簡單帝火,這里不貼出源碼。
setValue()
:
只能在主線程執(zhí)行湃缎,非主線程調(diào)用拋出異常犀填。
mVersion
+1,mData
設(shè)置為傳入數(shù)據(jù)嗓违,并通過dispatchingValue(null)
通知所有觀察者數(shù)據(jù)數(shù)據(jù)更新九巡。
注意數(shù)據(jù)設(shè)置時,不會進(jìn)行任何的對比和校驗(yàn)蹂季。即設(shè)置相同數(shù)據(jù)時冕广,同樣視為更新數(shù)據(jù)〕ソ啵·postValue()
:
在任意線程中調(diào)用撒汉,傳入的數(shù)據(jù)會暫存為mPendingData
,最終會通過在主線程中調(diào)用setValue(mPendingData)
進(jìn)行數(shù)據(jù)更新涕滋。
注意的是睬辐,postValue()
被多次調(diào)用時,暫存數(shù)據(jù)mPendingData
會被postValue()
傳入的數(shù)據(jù)覆蓋,最終數(shù)據(jù)為最后一次的數(shù)據(jù)溯饵。而postValue()
發(fā)起的主線程任務(wù)侵俗,在執(zhí)行到前,只會存在一個任務(wù)丰刊。即:
多次postValue()
調(diào)用隘谣,在真正主線程執(zhí)行前,共享同一次任務(wù)啄巧。而其中的暫存數(shù)據(jù)mPendingData
會被覆蓋為最后一次postValue()
的傳入值寻歧。
使用postValue()
應(yīng)該注意該問題,極短時間內(nèi)多次postValue()
設(shè)置數(shù)據(jù)棵帽,會可能導(dǎo)致數(shù)據(jù)更新丟失熄求。
-
LiveData.observeForever()
:
添加忽略生命周期偵測特性的觀察者渣玲。
通過該方法加入的觀察者不需要傳入生命周期參數(shù)逗概,即忽略生命周期偵測。
所以使用該方法時需要注意爽醋,在合適的時候調(diào)用removeObserver()
移除觀察调榄,避免發(fā)生內(nèi)存泄漏氛濒。
- 通過
observeForever()
傳入的觀察者,將會被包裝為AlwaysActiveObserver
铅搓,該包裝類的shouldBeActive()
方法估計(jì)返回true
,即任何數(shù)據(jù)更新都會通知到該觀察者搀捷。 - 同一個
LiveData
中星掰,觀察者不能同時 持有 / 忽略 生命周期特性,兩者互斥嫩舟。 - 新加入的觀察者氢烘,在方法的最后都會通過
activeStateChanged(true)
通知LiveData
更新數(shù)據(jù)到觀察者。
public void observeForever(Observer<? super T> observer) {
assertMainThread("observeForever");
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
- 觀察者移除:
觀察者移除有2個方法家厌,且都比較簡單播玖,這里不貼出源碼。
-
removeObserver(Observer observer)
:
該方法用于移除指定的觀察者饭于,如果綁定生命周期蜀踏,則會解除綁定。 -
removeObservers(LifecycleOwner owner)
:
僅針對通過LiveData.observe()
添加掰吕,綁定了生命周期的觀察者果覆,移除維護(hù)中的所有生命周期對象為傳入對象的觀察者。最終也是通過removeObserver()
逐一移除殖熟。