上篇博客分享了下Lifecycle,使用的技術也就是:觀察者模式+註解+反射。本篇博客繼續學習Jetpack的LiveData,其實這個東西是一種可觀察的數據存儲類。
LiveData自己可以作爲觀察者,觀察到數據變化,並回調給開發者。 它是可以監聽到Activity(Fragment)生命週期的變化,並且在Activity處於活躍狀態下,才發送時間通知開發者處理業務邏輯。
這個LiveData不是數據,是數據存儲類。
LiveData的使用
示例:一個按鈕,一個TextView , 點擊一個按鈕,TextView的值+1。
LiveData一般是結合ViewModel使用的,關於ViewModel,之後的博客再分享。 先創建一個類繼承自ViewModel:
/**
* author: liumengqiang
* Date : 2020/5/14
* Description :
*/
public class NameViewModel extends ViewModel {
//MutableLiveData繼承自LiveData
private MutableLiveData<String> name;
//暴露獲取方法
public MutableLiveData<String> getName() {
if(name == null) {
name = new MutableLiveData<>();
}
return name;
}
}
使用的話就很簡單了, 在Activity的onCreate方法中:
private int index = 0;
private TextView nameTextView;
private Button btn;
private NameViewModel nameViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_data);
//獲取或者創建ViewModel
nameViewModel =
new ViewModelProvider(this,
new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(NameViewModel.class);
//綁定LiveData到一個觀察者上
nameViewModel.getName().observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
nameTextView.setText(s);
}
});
nameTextView = findViewById(R.id.live_data_text);
btn = findViewById(R.id.live_data_btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//數據源改變
String name = "hello world " + (index ++);
nameViewModel.getName().setValue(name);
}
});
}
這個代碼就很簡單了,結果如下圖:
這個例子是很簡單的,LiveData強大之處就是: 既可以作爲觀察者,也可以作爲被觀察者。
作爲觀察者:能夠感知Activity或者Fragment的生命週期的變化。
作爲被觀察者:當數據改變能夠通知給開發者,以處理業務邏輯。
其內部原理是怎樣的呢?
LiveData源碼分析
在分析源碼之前我們看三個結論,
- LiveData是能夠感知組件生命週期的,當Activity處於活躍狀態時,才能夠收到數據,不處於活躍狀態是收不到事件的。
- LiveData在組件處於DESTROYED狀態下會移除Observer,解除綁定,避免內存泄漏
- 每次調用setValue更改數據源之後,如果組件從非活躍狀態到活躍狀態,組件此時接收到的是最新的數據,而中間發的很多的次變更都是無效的。
首先我們從訂閱開始:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//檢測是否在主線程
assertMainThread("observe");
//判斷組件是否是DESTROYED狀態。
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//將組件和Observer封裝成一個對象:LifecycleBoundObserver
//這個對象實現了LifecycleObserver接口
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//把所有的Observer和封裝的對象添加到了集合中
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
......
//這個是把LifecycleObserver實現對象和 組件綁定起來
//這樣就能夠感知組件的生命週期了。
owner.getLifecycle().addObserver(wrapper);
}
這裏做了主要三件事
- 檢測組件是否是處於DESTORYED狀態, 如果是,就直接返回
- 將組件和Observer封裝成了一個LifecycleObserver實現類對象,這個對象,存到了一個map中,這樣方便之後setValue分發數據
- 最後將LifecycleObserver實現類對象和組件綁定在一起,這樣能夠感知組件的生命週期變化了。
現在看下setValue方法,也就是改變LiveData裏面的數據源
//從這個註解可以看出來必須要在主線程調用
@MainThread
protected void setValue(T value) {
// 檢測是否在主線程
assertMainThread("setValue");
//定義了一個版本號
mVersion++;
//將值賦值給mData變量
mData = value;
//開始分發數據事件
dispatchingValue(null);
}
代碼註釋比較清晰了,主要是這個版本號:mVersion是個什麼東西呢? 爲什麼定義這個東西呢? mVersion就是記錄一下改變次數,每次setValue方法調用,也就是每次數據源改變,mVersion都會+1, 這個值接下來會和LifecycleBoundObserver實現類的mLastVersion對比的,具體下文解釋。
然後將value值賦值給了mData對象,這樣的話,試想一下,如果若此調用setValue方法,每次set 的值都不一樣,那麼是不是mData存儲的都是最後一次setValue的值呢? 答案是肯定的,存儲的就是最後一次setValue的值。
然後現在開始分發數據源改變的事件:
@SuppressWarnings("WeakerAccess") /* synthetic access */
void dispatchingValue(@Nullable ObserverWrapper initiator) {
........
do {
mDispatchInvalidated = false;
if (initiator != null) {
//initiator不是null, 也就是定向分發事件,
considerNotify(initiator);
initiator = null;
} else {
//initiator是null
// 循環之前map, 然後給每個觀察者都分發事件
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
由於此時傳入的dispatchingValue傳入的參數是null,所以是全部的觀察者都分發事件。
傳入initiator不是null的情況是在生命週期改變的情況下執行的,下文具體分析
private void considerNotify(ObserverWrapper observer) {
//判斷是否是處於活躍狀態
//是否是已經解綁
if (!observer.mActive) {
return;
}
//活躍狀態是:STARTED或者RESUMED
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//判斷Observer的mLastVersion和mVersion的大小
if (observer.mLastVersion >= mVersion) {
return;
}
//給Observer的mLastVersion重新賦值
observer.mLastVersion = mVersion;
//noinspection unchecked
//執行觀察者的onChaned回調
observer.mObserver.onChanged((T) mData);
}
這裏的ObserverWrapper observer對象實際上就是LifecycleBoundObserver, 這個在剛開始訂閱的時候內部創建的。它繼承自ObserverWrapper
LifecycleBoundObserver也實現了GenericLifecycleObserver,而GenericLifecycleObserver繼承自LifecycleEventObserver, 這個細節很重要,具體後續的代碼會着重分析。
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
//判斷是否是活躍狀態:STARTED或者RESUMED,
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//這個方法就是組件生命週期改變時, 調用的方法。傳入的參數一個是組件本身,一個是組件處於的狀態
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//當組件處於DESTROYED狀態時,也就是處於銷燬狀態時
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
//移除Observer,解除綁定
removeObserver(mObserver);
return;
}
//這個方法的實現是在父類ObserverWrapper中的
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
從LifecycleBoundObserver的具體實現,需要注意兩個知識點
- shouldBeActive方法是返回組件是否:STARTED或者RESUMED狀態,如果是就返回true
- onStateChanged方法是分析LiveData感知組件生命週期的重要點,具體我們下文分析。
在onStateChanged方法中調用了父類的activeStateChanged方法,看下具體實現:
void activeStateChanged(boolean newActive) {
//判斷活躍狀態是否等於上一次的狀態
if (newActive == mActive) {
return;
}
......
//
if (mActive) {
//如果是活躍狀態,那麼就分發數據源改變事件,傳入的參數是自己本身,
//也就是:LifecycleBoundObserver類的對象
dispatchingValue(this);
}
}
}
這時候對於dispatchingValue方法傳入的參數不是null, 是不是就是單次分發呢? 懵逼的,重新網上看下dispatchingValue方法。,進入到了if判斷裏面。
重新回到considerNotify方法,mLastVersion和mVersion的初始值都是-1, 但是每次setValue, mVersion的值都會+1, 但是mLastVersion的值還是-1, 所以(observer.mLastVersion >= mVersion) 不成立,將mVersion的值賦值給mLastVersion, 這樣mLastVersion就是最新的值了, 最後調用了我們熟悉的onChanged方法。
想一下considerNotify方法中爲什麼會有這三個if判斷呢?
首先前兩個判斷就是要保證組件處於活躍狀態; 此三個判斷就是要保證只接受最後一次的新數據,並且只執行一次。 Google這樣設計也是相當的巧妙!
這樣每次setValue 到 執行onChange方法流程就分析完了。
那麼它是怎樣感知生命週期的呢? 換句話說就是LifecycleBoundObserver的onStateChanged方法是什麼時候執行的呢?
這個問題,如果是看過Lifecycle源碼的,這個問題是相當簡單的。
記不記得我們剛開始調用LiveData的observe方法的時候,該方法的最後一句話:
owner.getLifecycle().addObserver(wrapper);
把封裝成的LifecycleBoundObserver類對象和組件綁定到了一塊, 這樣內部就通過 ReportFragment就能夠感知生命週期的變化了。詳見:Lifecycle源碼分析
這裏需要注意的一點是,當生命週期變化的時候,最終調用的dispatchEvent方法:
static class ObserverWithState {
State mState;
LifecycleEventObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
//這裏返回的直接是將observer轉成了LifecycleEventObserver。
mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
//調用了觀察者的onStateChanged方法
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
}
這裏的observer參數就是LifecycleBoundObserver類對象,上文說過LifecycleBoundObserver實現了LifecycleEventObserver接口,Lifecycling.lifecycleEventObserver(observer);
內部執行一通邏輯之後,做的操作是直接將observer轉成了LifecycleEventObserver接口對象。
ReportFragment生命週期的變化之後,調用的是LifecycleBoundObserver的onStateChanged方法,這樣是不是形成了閉環?!
重新理一下步驟:
setValue ——> onChanged流程
- 通過調用LiveData的observe方法,創建了LifecycleBoundObserver對象,並且綁定了組件和LifecycleBoundObserver實例。
- 每次setValue之後會調用dispatchingValue方法
- 在dispatchingValue方法內,會調用considerNotify方法
- 在considerNotify方法內,回到用觀察者的onChanged方法。
感知LiveData生命週期流程
- 通過調用LiveData的observe方法, 在這個方法最後一句話,綁定了組件和LifecycleBoundObserver類的實例對象。
- LifecycleRegister的addObserver方法內,將LifecycleBoundObserver類實例存儲到了一個map中。
- 在組件的內部創建了一個空白的ReportFragment, ReportFragment的生命週期是和組件的生命週期是同步的。
- 以Report Fragment的onStart方法爲例: 內部調用了
dispatch(Lifecycle.Event.ON_START);
- dispatch方法內調用handleLifecycleEvent方法, 該方法是在LifecycleRegister類內部的
- handleLifecycleEvent ——》 moveToState ——》 sync ——》 forwardPass ——》 dispatchEvent ——》 mLifecycleObserver.onStateChanged
- 最後回到了LifecycleBoundObserver的onStateChanged方法內,調用:activeStateChanged方法
- activeStateChanged ——》 dispatchingValue ——》 considerNotify ——》onChanged方法
這樣整個流程就完全了, 可能感知生命週期的流程比較懵逼的話,一定要看一下:Lifecycle源碼分析