Android Jetpack組件庫LiveData源碼深入探究
Android Jetpack之ViewModel、LiveData
Android Jetpack之DataBinding+ViewModel+LiveData+Room
前言
Jetpack是一個由多個技術(shù)庫組成的套件,可幫助開發(fā)者遵循最佳做法,減少樣板代碼并編寫可在各種Android版本和設(shè)備中一致運行的代碼,讓開發(fā)者精力集中編寫重要的代碼。
一、LiveData
LiveData 是一種持有可被觀察的數(shù)據(jù)存儲類。和其他可被觀察的類不同的是LiveData 可以在 Activity ,fragment 或者 service 生命周期發(fā)生改變時通知更新。LiveData 已經(jīng)是必不可少的一環(huán)了,例如 MVVM 以及 MVI 開發(fā)模式中,都用到了 LiveData。
(注意??源碼是Java代碼)
LIveData 的優(yōu)勢:
- 確保界面符合數(shù)據(jù)狀態(tài):數(shù)據(jù)發(fā)生變化時,就會通知觀察者。我們可以再觀察者回調(diào)中更新界面,這樣就無需在數(shù)據(jù)改變后手動更新界面了。
- 沒有內(nèi)存泄漏,因為關(guān)聯(lián)了生命周期,頁面銷毀后會進行自我清理。
- 不會因為Activity 停止而導(dǎo)致崩潰,頁面處于非活躍狀態(tài)時,他不會接收到任何 LiveData 事件。
- 共享資源,可以使用單例模式擴展 LiveData 對象,以便在應(yīng)用中共享他們。
- 屏幕翻轉(zhuǎn)數(shù)據(jù)狀態(tài)保留
- 不再需要手動處理生命周期
- 數(shù)據(jù)始終保持最新狀態(tài)
二、使用案例
LiveData 是一種可用于任何數(shù)據(jù)的封裝容器,通常 LiveData 存儲在 ViewModel 對象中。
class JokesDetailViewModel : ViewModel() {
//創(chuàng)建 LiveData
private val _state by lazy { MutableLiveData<JokesUIState>() }
val state : LiveData<JokesUIState> = _state
private fun loadChildComment(page: Int, commentId: Int, parentPos: Int, curPos: Int) {
viewModelScope.launch {
launchHttp {
jokesApi.jokesCommentListItem(commentId, page)//請求數(shù)據(jù)
}.toData {
//通知觀察者
_state.value = JokesUIState.LoadMoreChildComment(it.data, parentPos, curPos)
}
}
}
}
//觀察 LiveData
viewModel.state.observe(this, Observer {
//更新 UI
})三、LiveData 實現(xiàn)原理

- Observer:觀察者接口;
- LiveData:發(fā)送已經(jīng)添加觀察的邏輯都在其中;
- ObserverWrapper:抽象的觀察者包裝類;
- LifecycleBoundleObserver:繼承 ObserverWrapper;
- LifecycleEventObserver,生命周期相關(guān)回調(diào);
observe(this,Observer{})
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//如果已經(jīng)銷毀,直接退出
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
//包裝類(下面源碼)
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//判斷是否已添加
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
//....
}
//之前添加過
if (existing != null) {
return;
}
//注冊 lifecycle,生命周期改變時會回調(diào)
owner.getLifecycle().addObserver(wrapper);
}LifecycleBoundObserver(owner, observer)
class LifecycleBoundObserver
extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
//當(dāng)前狀態(tài)大于或者等于 STARTED 返回 true
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//生命周期相關(guān)回調(diào)
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
//如果已經(jīng)銷毀,移除觀察者
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
//循環(huán)更新狀態(tài)
while (prevState != currentState) {
prevState = currentState;
//修改活躍狀態(tài)
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}- 繼承 ObserverWrapper 的包裝類--activeStateChanged(..)方法。
- 實現(xiàn)LifecycleEventObserver 接口--onStateChanged(..)方法。
ObserverWrapper.activeStateChanged()
void activeStateChanged(boolean newActive) {
//如果等于之前狀態(tài)
if (newActive == mActive) {
return;
}
mActive = newActive;
//活躍 +1,不活躍 -1 (下面有源碼)
changeActiveCounter(mActive ? 1 : -1);
//如果狀態(tài)變成了活躍狀態(tài),直接調(diào)用 dispatchingValue,傳入當(dāng)前的觀察者
if (mActive) {
dispatchingValue(this); //(下面有源碼)
}
}
//修改活躍數(shù)量
void changeActiveCounter(int change) {
int previousActiveCount = mActiveCount;//之前活躍的數(shù)量
mActiveCount += change;//總活躍數(shù)量
if (mChangingActiveState) {//如果正在更改,退出
return;
}
mChangingActiveState = true;//更改中
try {
while (previousActiveCount != mActiveCount) {
boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
previousActiveCount = mActiveCount;
//如果當(dāng)前是第一個激活的,調(diào)用 onActive
if (needToCallActive) {
onActive();//當(dāng)活動的觀察者從0 變成 1的時候調(diào)用
//如果沒有激活的為 0 ,調(diào)用 onInactive
} else if (needToCallInactive) {
onInactive();//活躍的觀察者變成 0 時調(diào)用
}
}
} finally {
mChangingActiveState = false;
}
}
//分發(fā)數(shù)據(jù)
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return; //如果正在分發(fā),退出
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//如果觀察者不為空
if (initiator != null) {
considerNotify(initiator);//對數(shù)據(jù)進行派發(fā),通知觀察者
initiator = null;
} else {
//如果為空,遍歷所有的觀察者,將數(shù)據(jù)發(fā)送給所有觀察者
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ù)據(jù)進行派發(fā),通知觀察者
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
//再次進行判斷,如果不活躍,則會更新狀態(tài),然后退出
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//觀察者版本是否低于當(dāng)前的版本
//初始值 mLastVersion 為 -1,mVersion 為 0
//小于等于表示沒有需要更新的數(shù)據(jù)
if (observer.mLastVersion >= mVersion) {
return;
}
//更新版本
observer.mLastVersion = mVersion;
//通知觀察者
observer.mObserver.onChanged((T) mData);
}梳理流程:
1、通過 observe 添加一個觀察者,這個觀察者會被 LifecycleBoundObserver 進行一個封裝,LifecycleBoundObserver繼承 ObserverWrapper,并且實現(xiàn)了 LifecycleEventObserver。之后就會將觀察添加到 Observers 中,最后注冊頁面生命周期的 observer。
2、當(dāng)生命周期發(fā)生變化后,就會回調(diào)到 LifecycleBoundObserve 中的 onStateChanged 方法中。如果生命周期是銷毀的,就會移除觀察者,如果不是就會循環(huán)更新當(dāng)前狀態(tài)。
3、在更新狀態(tài)的時候就會判斷是否為活躍狀態(tài),如果是活躍狀態(tài)就會進行分發(fā),分發(fā)的時候如果觀察者為 null ,就會遍歷所有的觀察者進行分發(fā),否則就分發(fā)傳入的觀察者。
4、最后會再次判斷活躍狀態(tài),已經(jīng)判斷觀察者版本是否低于當(dāng)前版本,如果都滿足,就會更新觀察者。
onActive 與 onInactive
如果觀察者的生命周期處于 STARTED 或者 RESUMED 狀態(tài),LiveData 就會認為觀察者處于活躍狀態(tài)。
例如,下載數(shù)據(jù)需要在活躍狀態(tài)下進行,或者需要實時的監(jiān)聽后臺數(shù)據(jù),就可以重新下面方法,并完成對應(yīng)邏輯。
class StockLiveData(url: String) : LiveData<String>() {
private val downloadManager = DownloadManager(url)
override fun onActive() {
if(!downloadManager.isStart()){
downloadManager.start()
}
}
override fun onInactive() {
downloadManager.stop()
}
}當(dāng)具有活躍的觀察者時,就會調(diào)用 onActive 方法。
當(dāng)沒有任何活躍的觀察者時,就會調(diào)用 onInactive 方法。
當(dāng)然這只是我想到的場景,開發(fā)中可以根據(jù)不同的業(yè)務(wù)場景做出不同的判斷。
四、LiveData 相關(guān)源碼
MutableLiveData
由于 LiveData 的發(fā)送數(shù)據(jù)方法是 protected 修飾私有受保護的,所以不能直接調(diào)用。因此使用MutableLiveData 繼承 LiveData 將發(fā)送數(shù)據(jù)的方法改為了 public。
public class MutableLiveData<T> extends LiveData<T> {
/**
* Creates a MutableLiveData initialized with the given {@code value}.
*/
public MutableLiveData(T value) {
super(value);
}
/**
* Creates a MutableLiveData with no value assigned to it.
*/
public MutableLiveData() {
super();
}
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}Transformations.map()
在數(shù)據(jù)分發(fā)給觀察者之前對其中存儲的值進行更改,返回一個新的 LiveData,可以使用此方法。
val strLiveData = MutableLiveData<String>()
val strLengthLiveData = Transformations.map(strLiveData) {
it.length
}
strLiveData.observe(this) {
Log.e("---345---> str:", "$it");
}
strLengthLiveData.observe(this) {
Log.e("---345---> strLength:", "$it");
}
strLiveData.value = "hello word"
E/---345---> str:: hello word
E/---345---> strLength:: 10Transformations.switchMap()
對上面的做了個判斷,根據(jù)不同的需求返回不同的 LiveData。也可以通過 id 去判斷,返回對應(yīng)的 livedata 即可。
val idLiveData = MutableLiveData<Int>()
val userLiveData = Transformations.switchMap(idLiveData) { id->
getUser(id)
}合并多個 LiveData
val live1 = MutableLiveData<String>()
val live2 = MutableLiveData<String>()
val mediator = MediatorLiveData<String>()
mediator.addSource(live1) {
mediator.value = it
Log.e("---345---> live1", "$it");
}
mediator.addSource(live2){
mediator.value = it
Log.e("---345---> live2", "$it");
}
mediator.observe(this, Observer {
Log.e("---345---> mediator", "$it");
})
live1.value = "hello"
E/---345---> mediator: hello
E/---345---> live1: hello通過 MediatorLiveData 將兩個 MutableLiveData 合并到一起,這樣當(dāng)任何一個發(fā)生變化,MediatorLiveData 都可以感知到。
五、LiveData分發(fā)問題
數(shù)據(jù)粘性事件
例如再沒有觀察者的時候發(fā)送數(shù)據(jù),此時 mVersion +1,等到真正添加了觀察者后,生命周期也是活躍的,那么就會將這個數(shù)據(jù)重新分發(fā)到觀察者。所以說發(fā)送數(shù)據(jù)這個操作是粘性的。
如果需要去除粘性事件,可以在添加完 observe 后去通過反射修改 mVersion 和 觀察者包裝類中的 mLastVersion 的值,將 mVersion 賦值給 mLastVersion 即可去掉粘性事件。
數(shù)據(jù)倒灌現(xiàn)象
一般情況下,LiveData 都是存放在 ViewModel 中的,當(dāng)Activity重建的時候,觀察者會被 remove 掉,重建后會添加一個新的觀察者,添加后新的觀察者版本號就是 -1,所以就會出現(xiàn)數(shù)據(jù)再次被接收到。
這種解決方式和上面一樣,反射修改版本號就可以解決。非活躍狀態(tài)的觀察者轉(zhuǎn)為活躍狀態(tài)后,只能接收到最后一次發(fā)送的數(shù)據(jù)。一般情況下我們都需要的是最新數(shù)據(jù),如果非要所有數(shù)據(jù),只能重寫 LiveData 了。
到此這篇關(guān)于Android Jetpack組件庫LiveData源碼深入探究的文章就介紹到這了,更多相關(guān)Android Jetpack LiveData內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android?Jetpack?組件LiveData源碼解析
- Android Jetpack 狠活Lifecycles與LiveData使用詳解
- Android Jetpack組件支持庫DataBinding與ViewModel與LiveData及Room詳解
- Android開發(fā)Jetpack組件ViewModel與LiveData使用講解
- Android開發(fā)Jetpack組件LiveData使用講解
- Android?Jetpack庫剖析之LiveData組件篇
- 詳解Android JetPack之LiveData的工作原理
- Android Jetpack組件中LiveData的優(yōu)劣
相關(guān)文章
Android使用Jetpack WindowManager開發(fā)可折疊設(shè)備(過程分享)
這篇文章主要介紹了Android使用Jetpack WindowManager開發(fā)可折疊設(shè)備,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-11-11
Android如何判斷當(dāng)前點擊位置是否在圓的內(nèi)部
這篇文章主要為大家詳細介紹了Android如何判斷當(dāng)前點擊位置是否在圓的內(nèi)部,解析拖動圓形控件之內(nèi)響應(yīng)觸摸事件,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05
Android開發(fā)之在xml中設(shè)置自定義屬性的方法
下面小編就為大家分享一篇Android開發(fā)之在xml中設(shè)置自定義屬性的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01
Android應(yīng)用開發(fā)中使用Fragment的入門學(xué)習(xí)教程
這篇文章主要介紹了Android應(yīng)用開發(fā)中Fragment的入門學(xué)習(xí)教程,可以把Fragment看作為Activity基礎(chǔ)之上的模塊,需要的朋友可以參考下2016-02-02

