Jetpack AAC 系列文章:
“終於懂了“系列:Jetpack AAC完整解析(-)Lifecycle 完全掌握!
“終於懂了“系列:Jetpack AAC完整解析(二)LiveData 完全掌握!
......
上一篇介紹了Jetpack AAC 的基礎組件 Lifecycle,它是用於管理Activity/Fragment的生命週期。這篇來介紹基於Lifecycle的用於處理數據的組件——LiveData。
一、LiveData介紹
1.1 作用
LiveData是Jetpack AAC的重要組件,同時也有一個同名抽象類。
LiveData,原意是 活着的數據。 數據還能有生命? 先來看下官方的定義:
LiveData 是一種可觀察的數據存儲器類。與常規的可觀察類不同,LiveData 具有生命週期感知能力,意指它遵循其他應用組件(如 Activity/Fragment)的生命週期。這種感知能力可確保 LiveData 僅更新處於活躍生命週期狀態的應用組件觀察者。
拆解開來:
- LiveData是一個數據持有者,給源數據包裝一層。
- 源數據使用LiveData包裝後,可以被observer觀察,數據有更新時observer可感知。
- 但 observer的感知,只發生在(Activity/Fragment)活躍生命週期狀態(STARTED、RESUMED)。
也就是說,LiveData使得 數據的更新 能以觀察者模式 被observer感知,且此感知只發生在 LifecycleOwner的活躍生命週期狀態。
1.2 特點
使用 LiveData 具有以下優勢:
- 確保界面符合數據狀態,當生命週期狀態變化時,LiveData通知Observer,可以在observer中更新界面。觀察者可以在生命週期狀態更改時刷新界面,而不是在每次數據變化時刷新界面。
- 不會發生內存泄漏,observer會在LifecycleOwner狀態變爲DESTROYED後自動remove。
- 不會因 Activity 停止而導致崩潰,如果LifecycleOwner生命週期處於非活躍狀態,則它不會接收任何 LiveData事件。
- 不需要手動解除觀察,開發者不需要在onPause或onDestroy方法中解除對LiveData的觀察,因爲LiveData能感知生命週期狀態變化,所以會自動管理所有這些操作。
- 數據始終保持最新狀態,數據更新時 若LifecycleOwner爲非活躍狀態,那麼會在變爲活躍時接收最新數據。例如,曾經在後臺的 Activity 會在返回前臺後,observer立即接收最新的數據。
二、LiveData的使用
下面介紹LiveData的使用,掌握使用方法也可以更好理解上面的內容。
2.1基本使用
gradle依賴在上一篇中已經介紹了。下面來看基本用法:
- 創建LiveData實例,指定源數據類型
- 創建Observer實例,實現onChanged()方法,用於接收源數據變化並刷新UI
- LiveData實例使用observe()方法添加觀察者,並傳入LifecycleOwner
- LiveData實例使用setValue()/postValue()更新源數據 (子線程要postValue())
舉個例子:
public class LiveDataTestActivity extends AppCompatActivity{
private MutableLiveData<String> mLiveData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle_test);
//liveData基本使用
mLiveData = new MutableLiveData<>();
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "onChanged: "+s);
}
});
Log.i(TAG, "onCreate: ");
mLiveData.setValue("onCreate");//activity是非活躍狀態,不會回調onChanged。變爲活躍時,value被onStart中的value覆蓋
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "onStart: ");
mLiveData.setValue("onStart");//活躍狀態,會回調onChanged。並且value會覆蓋onCreate、onStop中設置的value
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "onResume: ");
mLiveData.setValue("onResume");//活躍狀態,回調onChanged
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "onPause: ");
mLiveData.setValue("onPause");//活躍狀態,回調onChanged
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "onStop: ");
mLiveData.setValue("onStop");//非活躍狀態,不會回調onChanged。後面變爲活躍時,value被onStart中的value覆蓋
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy: ");
mLiveData.setValue("onDestroy");//非活躍狀態,且此時Observer已被移除,不會回調onChanged
}
}
注意到 LiveData實例mLiveData的創建是使用MutableLiveData,它是LiveData的實現類,且指定了源數據的類型爲String。然後創建了接口Observer的實例,實現其onChanged()方法,用於接收源數據的變化。observer和Activity一起作爲參數調用mLiveData的observe()方法,表示observer開始觀察mLiveData。然後Activity的所有生命週期方法中都調用了mLiveData的setValue()方法。 結果日誌打印如下:
//打開頁面,
2020-11-22 20:23:29.865 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onCreate:
2020-11-22 20:23:29.867 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onStart:
2020-11-22 20:23:29.868 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onStart
2020-11-22 20:23:29.869 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onResume:
2020-11-22 20:23:29.869 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onResume
//按Home鍵
2020-11-22 20:23:34.349 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onPause:
2020-11-22 20:23:34.349 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onPause
2020-11-22 20:23:34.368 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onStop:
//再點開
2020-11-22 20:23:39.145 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onStart:
2020-11-22 20:23:39.146 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onStart
2020-11-22 20:23:39.147 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onResume:
2020-11-22 20:23:39.147 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onResume
//返回鍵退出
2020-11-22 20:23:56.753 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onPause:
2020-11-22 21:23:56.753 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onPause
2020-11-22 20:23:58.320 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onStop:
2020-11-22 20:23:58.322 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onDestroy:
首先打開頁面,onCreate()中setValue,由於activity是非活躍狀態,不會立即回調onChanged。當走到onStart()變爲活躍時,onChanged被調用,但value被onStart()中setValue的value覆蓋,所以打印的是onChanged: onStart。(爲啥不是連續打印兩次呢?,是因爲ON_START事件是在onStart() return之後,即onStart()走完之後才變爲活躍<詳見上一篇>,此時observer接收最新的數據。) 接着走到onResume(),也setValue了,同樣是活躍狀態,所以立刻回調onChanged,打印onChanged: onResume
按Home鍵時,onPause()中setValue,活躍狀態,立刻回調onChanged方法。onStop()執行時已經變爲非活躍狀態,此時setValue不會立即回調onChanged方法。
再點開時,走到onStart()變爲活躍時,onChanged被調用,但value被onStart()中setValue的value覆蓋,所以打印的是onChanged: onStart。接着走到onResume(),也setValue了,同樣是活躍狀態,所以立刻回調onChanged。
返回鍵退出時,onPause()/onStop()的效果和按Home鍵一樣。onDestroy()中setValue,此時非活躍狀態,且此時observer已被移除,不會回調onChanged。
另外,除了使用observe()方法添加觀察者,也可以使用observeForever(Observer) 方法來註冊未關聯 LifecycleOwner的觀察者。在這種情況下,觀察者會被視爲始終處於活躍狀態。
2.2 擴展使用
擴展包括兩點:
- 自定義LiveData,本身回調方法的覆寫:onActive()、onInactive()。
- 實現LiveData爲單例模式,便於在多個Activity、Fragment之間共享數據。
官方的例子如下:
public class StockLiveData extends LiveData<BigDecimal> {
private static StockLiveData sInstance; //單實例
private StockManager stockManager;
private SimplePriceListener listener = new SimplePriceListener() {
@Override
public void onPriceChanged(BigDecimal price) {
setValue(price);//監聽到股價變化 使用setValue(price) 告知所有活躍觀察者
}
};
//獲取單例
@MainThread
public static StockLiveData get(String symbol) {
if (sInstance == null) {
sInstance = new StockLiveData(symbol);
}
return sInstance;
}
private StockLiveData(String symbol) {
stockManager = new StockManager(symbol);
}
//活躍的觀察者(LifecycleOwner)數量從 0 變爲 1 時調用
@Override
protected void onActive() {
stockManager.requestPriceUpdates(listener);//開始觀察股價更新
}
//活躍的觀察者(LifecycleOwner)數量從 1 變爲 0 時調用。這不代表沒有觀察者了,可能是全都不活躍了。可以使用hasObservers()檢查是否有觀察者。
@Override
protected void onInactive() {
stockManager.removeUpdates(listener);//移除股價更新的觀察
}
}
爲了觀察股票價格變動,繼承LiveData自定義了StockLiveData,且爲單例模式,只能通過get(String symbol)方法獲取實例。 並且重寫了onActive()、onInactive(),並加入了 開始觀察股價更新、移除股價更新觀察 的邏輯。
- onActive()調用時機爲:活躍的觀察者(LifecycleOwner)數量從 0 變爲 1 時。
- onInactive()調用時機爲:活躍的觀察者(LifecycleOwner)數量從 1 變爲 0 時。
也就是說,只有當 存在活躍的觀察者(LifecycleOwner)時 纔會連接到 股價更新服務 監聽股價變化。使用如下:
public class MyFragment extends Fragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//獲取StockLiveData單實例,添加觀察者,更新UI
StockLiveData.get(symbol).observe(getViewLifecycleOwner(), price -> {
// Update the UI.
});
}
}
由於StockLiveData是單實例模式,那麼多個LifycycleOwner(Activity、Fragment)間就可以共享數據了。
2.3 高級用法
如果希望在將 LiveData 對象分派給觀察者之前對存儲在其中的值進行更改,或者需要根據另一個實例的值返回不同的 LiveData 實例,可以使用LiveData中提供的Transformations類。
2.3.1 數據修改 - Transformations.map
//Integer類型的liveData1
MutableLiveData<Integer> liveData1 = new MutableLiveData<>();
//轉換成String類型的liveDataMap
LiveData<String> liveDataMap = Transformations.map(liveData1, new Function<Integer, String>() {
@Override
public String apply(Integer input) {
String s = input + " + Transformations.map";
Log.i(TAG, "apply: " + s);
return s;
}
});
liveDataMap.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "onChanged1: "+s);
}
});
liveData1.setValue(100);
使用很簡單:原本的liveData1 沒有添加觀察者,而是使用Transformations.map()方法 對liveData1的數據進行的修改 生成了新的liveDataMap,liveDataMap添加觀察者,最後liveData1設置數據 。
此例子把 Integer類型的liveData1 修改爲String類型的liveDataMap。結果如下:
2020-12-06 17:01:56.095 21998-21998/com.hfy.androidlearning I/Lifecycle_Test: apply: 100 + Transformations.map
2020-12-06 17:01:56.095 21998-21998/com.hfy.androidlearning I/Lifecycle_Test: onChanged1: 100 + Transformations.map
2.3.2 數據切換 - Transformations.switchMap
如果想要根據某個值 切換觀察不同LiveData數據,則可以使用Transformations.switchMap()方法。
//兩個liveData,由liveDataSwitch決定 返回哪個livaData數據
MutableLiveData<String> liveData3 = new MutableLiveData<>();
MutableLiveData<String> liveData4 = new MutableLiveData<>();
//切換條件LiveData,liveDataSwitch的value 是切換條件
MutableLiveData<Boolean> liveDataSwitch = new MutableLiveData<>();
//liveDataSwitchMap由switchMap()方法生成,用於添加觀察者
LiveData<String> liveDataSwitchMap = Transformations.switchMap(liveDataSwitch, new Function<Boolean, LiveData<String>>() {
@Override
public LiveData<String> apply(Boolean input) {
//這裏是具體切換邏輯:根據liveDataSwitch的value返回哪個liveData
if (input) {
return liveData3;
}
return liveData4;
}
});
liveDataSwitchMap.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "onChanged2: " + s);
}
});
boolean switchValue = true;
liveDataSwitch.setValue(switchValue);//設置切換條件值
liveData3.setValue("liveData3");
liveData4.setValue("liveData4");
liveData3、liveData4是兩個數據源,有一個判斷條件來決定 取哪一個數據 ,這個條件就是liveDataSwitch,如果值爲true則取liveData3,false則取liveData4。 Transformations.switchMap()就用於實現這一邏輯,返回值liveDataSwitchMap添加觀察者就可以了。 結果如下:
2020-12-06 17:33:53.844 27347-27347/com.hfy.androidlearning I/Lifecycle_Test: switchValue=true
2020-12-06 17:33:53.847 27347-27347/com.hfy.androidlearning I/Lifecycle_Test: onChanged2: liveData3
2020-12-06 17:34:37.600 27628-27628/com.hfy.androidlearning I/Lifecycle_Test: switchValue=false
2020-12-06 17:34:37.602 27628-27628/com.hfy.androidlearning I/Lifecycle_Test: onChanged2: liveData4
(Transformations對LivaData這兩個用法和Rxjava簡直一毛一樣)
2.3.3 觀察多個數據 - MediatorLiveData
MediatorLiveData 是 LiveData 的子類,允許合併多個 LiveData 源。只要任何原始的 LiveData 源對象發生更改,就會觸發 MediatorLiveData 對象的觀察者。
MediatorLiveData<String> mediatorLiveData = new MediatorLiveData<>();
MutableLiveData<String> liveData5 = new MutableLiveData<>();
MutableLiveData<String> liveData6 = new MutableLiveData<>();
//添加 源 LiveData
mediatorLiveData.addSource(liveData5, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "onChanged3: " + s);
mediatorLiveData.setValue(s);
}
});
//添加 源 LiveData
mediatorLiveData.addSource(liveData6, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "onChanged4: " + s);
mediatorLiveData.setValue(s);
}
});
//添加觀察
mediatorLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "onChanged5: "+s);
//無論liveData5、liveData6更新,都可以接收到
}
});
liveData5.setValue("liveData5");
//liveData6.setValue("liveData6");
例如,如果界面中有可以從本地數據庫或網絡更新的 LiveData 對象,則可以向 MediatorLiveData 對象添加以下源:
- 與存儲在本地數據庫中的數據關聯的 liveData5
- 與從網絡訪問的數據關聯的 liveData6
Activity 只需觀察 MediatorLiveData 對象即可從這兩個源接收更新。
結果如下:
2020-12-06 17:56:17.870 29226-29226/com.hfy.androidlearning I/Lifecycle_Test: onChanged3: liveData5
2020-12-06 17:56:17.870 29226-29226/com.hfy.androidlearning I/Lifecycle_Test: onChanged5: liveData5
(Transformations也是對MediatorLiveData的使用。)
LiveData的使用就講完了,下面開始源碼分析。
三、源碼分析
前面提到 LiveData幾個特點,能感知生命週期狀態變化、不用手動解除觀察等等,這些是如何做到的呢?
3.1 添加觀察者
LiveData原理是觀察者模式,下面就先從LiveData.observe()方法看起:
/**
* 添加觀察者. 事件在主線程分發. 如果LiveData已經有數據,將直接分發給observer。
* 觀察者只在LifecycleOwner活躍時接受事件,如果變爲DESTROYED狀態,observer自動移除。
* 當數據在非活躍時更新,observer不會接收到。變爲活躍時 將自動接收前面最新的數據。
* LifecycleOwner非DESTROYED狀態時,LiveData持有observer和 owner的強引用,DESTROYED狀態時自動移除引用。
* @param owner 控制observer的LifecycleOwner
* @param observer 接收事件的observer
*/
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// LifecycleOwner是DESTROYED狀態,直接忽略
return;
}
//使用LifecycleOwner、observer 組裝成LifecycleBoundObserver,添加到mObservers中
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers中.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
//!existing.isAttachedTo(owner)說明已經添加到mObservers中的observer指定的owner不是傳進來的owner,就會報錯“不能添加同一個observer卻不同LifecycleOwner”
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;//這裏說明已經添加到mObservers中,且owner就是傳進來的owner
}
owner.getLifecycle().addObserver(wrapper);
}
首先是判斷LifecycleOwner是DESTROYED狀態,就直接忽略,不能添加。接着使用LifecycleOwner、observer 組裝成LifecycleBoundObserver包裝實例wrapper,使用putIfAbsent方法observer-wrapper作爲key-value添加到觀察者列表mObservers中。(putIfAbsent意思是隻有列表中沒有這個observer時纔會添加。)
然後對添加的結果進行判斷,如果mObservers中已經存在此observer key,但value中的owner不是傳進來的owner,就會報錯“不能添加同一個observer卻是不同LifecycleOwner”。如果是相同的owner,就直接returne。
最後用LifecycleOwner的Lifecycle添加observer的封裝wrapper。
另外,再看observeForever方法:
@MainThread
public void observeForever(@NonNull 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);
}
和observe()類似,只不過 會認爲觀察者一直是活躍狀態,且不會自動移除觀察者。
3.2 事件回調
LiveData添加了觀察者LifecycleBoundObserver,接着看如何進行回調的:
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() { //至少是STARTED狀態
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);//LifecycleOwner變成DESTROYED狀態,則移除觀察者
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
LifecycleBoundObserver是LiveData的內部類,是對原始Observer的包裝,把LifecycleOwner和Observer綁定在一起。當LifecycleOwner處於活躍狀態,就稱 LifecycleBoundObserver是活躍的觀察者。
它實現自接口LifecycleEventObserver,實現了onStateChanged方法。上一篇Lifecycle中提到onStateChanged是生命週期狀態變化的回調。
在LifecycleOwner生命週期狀態變化時 判斷如果是DESTROYED狀態,則移除觀察者。LiveData自動移除觀察者特點就來源於此。 如果不是DESTROYED狀態,將調用父類ObserverWrapper的activeStateChanged()方法處理 這個生命週期狀態變化,shouldBeActive()的值作爲參數,至少是STARTED狀態爲true,即活躍狀態爲true。
private abstract class ObserverWrapper {
...
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;//活躍狀態 未發生變化時,不會處理。
}
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;//沒有活躍的觀察者
LiveData.this.mActiveCount += mActive ? 1 : -1;//mActive爲true表示變爲活躍
if (wasInactive && mActive) {
onActive();//活躍的觀察者數量 由0變爲1
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive(); //活躍的觀察者數量 由1變爲0
}
if (mActive) {
dispatchingValue(this);//觀察者變爲活躍,就進行數據分發
}
}
}
ObserverWrapper也是LiveData的內部類。mActive是ObserverWrapper的屬性,表示此觀察者是否活躍。如果活躍狀態 未發生變化時,不會處理。
LiveData.this.mActiveCount == 0 是指 LiveData 的活躍觀察者數量。活躍的觀察者數量 由0變爲1、由1變爲0 會分別調用LiveData的 onActive()、onInactive()方法。這就是前面提到的擴展使用
的回調方法。
最後觀察者變爲活躍,就使用LiveData的dispatchingValue(observerWrapper)進行數據分發:
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;//如果當前正在分發,則分發無效,return
return;
}
mDispatchingValue = true; //標記正在分發
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator); //observerWrapper不爲空,使用considerNotify()通知真正的觀察者
initiator = null;
} else { //observerWrapper爲空,遍歷通知所有的觀察者
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
如果當前正在分發,則分發無效;observerWrapper不爲空,就使用considerNotify()通知真正的觀察者,observerWrapper爲空 則遍歷通知所有的觀察者。 observerWrapper啥時候爲空呢?這裏先留個疑問。 繼續看considerNotify()方法:
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return; //觀察者非活躍 return
}
//若當前observer對應owner非活躍,就會再調用activeStateChanged方法,並傳入false,其內部會再次判斷
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);//回調真正的mObserver的onChanged方法
}
先進行狀態檢查:觀察者是非活躍就return;若當前observer對應的owner非活躍,就會再調用activeStateChanged方法,並傳入false,其內部會再次判斷。最後回調真正的mObserver的onChanged方法,值是LivaData的變量mData。
到這裏回調邏輯也通了。
3.3 數據更新
LivaData數據更新可以使用setValue(value)、postValue(value),區別在於postValue(value)用於 子線程:
//LivaData.java
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方法
}
};
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);//拋到主線程
}
postValue方法把Runable對象mPostValueRunnable拋到主線程,其run方法中還是使用的setValue(),繼續看:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
setValue()把value賦值給mData,然後調用dispatchingValue(null),參數是null,對應前面提到的observerWrapper爲空的場景,即 遍歷所有觀察者 進行分發回調。
到這裏觀察者模式完整的實現邏輯就梳理清晰了:LivaData通過observe()添加 與LifecycleOwner綁定的觀察者;觀察者變爲活躍時回調最新的數據;使用setValue()、postValue()更新數據時會通知回調所有的觀察者。
3.4 Transformations原理
最後來看下Transformations的map原理,如何實現數據修改的。switchMap類似的。
//Transformations.java
public static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source,@NonNull final Function<X, Y> mapFunction) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
@Override
public void onChanged(@Nullable X x) {
result.setValue(mapFunction.apply(x));
}
});
return result;
}
new了一個MediatorLiveData實例,然後將 傳入的livaData、new的Observer實例作爲參數 調用addSource方法:
//MediatorLiveData.java
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
Source<S> e = new Source<>(source, onChanged);
Source<?> existing = mSources.putIfAbsent(source, e);
if (existing != null && existing.mObserver != onChanged) {
throw new IllegalArgumentException(
"This source was already added with the different observer");
}
if (existing != null) {
return;
}
if (hasActiveObservers()) {
//MediatorLiveData有活躍觀察者,就plug
e.plug();
}
}
MediatorLiveData是LiveData的子類,用來觀察其他的LiveData並在其OnChanged回調時 做出響應。傳入的livaData、Observer 包裝成Source實例,添加到列表mSources中。
如果MediatorLiveData有活躍觀察者,就調用plug():
//MediatorLiveData.java
private static class Source<V> implements Observer<V> {
final LiveData<V> mLiveData;
final Observer<? super V> mObserver;
int mVersion = START_VERSION;
Source(LiveData<V> liveData, final Observer<? super V> observer) {
mLiveData = liveData;
mObserver = observer;
}
void plug() {
mLiveData.observeForever(this);//observeForever
}
void unplug() {
mLiveData.removeObserver(this);
}
@Override
public void onChanged(@Nullable V v) {
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
mObserver.onChanged(v);//源LiveData數據變化時及時回調到 傳入的
}
}
}
Source是MediatorLiveData的內部類,是對源LiveData的包裝。plug()中讓源LiveData調用observeForever方法添加永遠觀察者-自己。 這裏爲啥使用observeForever方法呢,這是因爲源LiveData在外部使用時不會調用observer方法添加觀察者,這裏永遠觀察是爲了在源LiveData數據變化時及時回調到 mObserver.onChanged(v)方法,也就是Transformations map方法中的nChanged方法。 而在e.plug()前是有判斷 MediatorLiveData 確認有活躍觀察者的。
最後map方法中的nChanged方法中有調用MediatorLiveData實例的setValue(mapFunction.apply(x)); 並返回實例。而mapFunction.apply()就是map方法傳入的修改邏輯Function實例。
最後類關係圖:
四、總結
本文先介紹了LiveData的概念——使用觀察者並可以感知生命週期,然後是使用方式、自定義LivaData、高級用法Transformations。最後詳細分析了LiveData源碼及原理。
並且可以看到Lifecycle如何在LiveData中發揮作用,理解了觀察者模式在其中的重要運用。LiveData是我們後續建立MVVM架構的核心。 LiveData同樣是我們必須掌握和理解的部分。
下一篇將介紹ViewModel,同樣是AAC中的核心內容。 今天就到這裏啦~
.
感謝與參考:
Android Jetpack架構組件(五)一文帶你瞭解LiveData(原理篇)
.
你的 點贊、評論,是對我的巨大鼓勵!
歡迎關注我的 公 衆 號,微信搜索 胡飛洋 ,文章更新可第一時間收到。