LiveData
是androidx.lifecycle-livedata包下的一個抽象類,實現了一種關聯了生命週期的簡單觀察者模式,主要的功能就是用於視圖層與數據間的單向一對多通知,一個LiveData
會持有一個可觀察的Data對象,一開始是處於NOT_SET
狀態,當用戶經過setValue方法更新後,LiveData
會遍歷全部的observer(處於Active狀態的),通知他們Data的更新.LiveData
的行爲會在Lifecycle
範圍內,避免不少Activity Leak和空指針//聲明一個LiveData
val data:MutableLiveData<String> = MutableLiveData()
//在須要的地方訂閱,observer的onChange方法會回調
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保存數據/監聽數據更改
class MyViewModel:ViewModel(){
val data:MutableLiveData<String> = MutableLiveData()
}
複製代碼
private val userLiveData:MutableLiveData<User> = MutableLiveData()
val userNames:LiveData<String> = Transformations
.map(userLiveData){
user ->
user.name
}
複製代碼
Transformations在androidx.lifecycle包下java
//聲明
val mediatorLiveData:MediatorLiveData<String> = MediatorLiveData()
//其餘合適的地方添加source
mediatorLiveData.addSource(stringFromNetwork){
mediatorLiveData.value = it
}
mediatorLiveData.addSource(stringFromDatabase){
mediatorLiveData.value = it
}
複製代碼
ViewModel
能夠在一個LifecycleOwner
的onCreate
到OnDestroy
之間保存實例不受到屏幕旋轉等ConfigChange的影響Activity/Fragment
持有ViewModel
,而ViewModel
持有各種LiveData
,Activity/Fragment
註冊觀察須要的數據,實現數據與UI的同步,並且不會所以發生Activity
泄漏,甚至能夠用ViewModel
來進行Activity/Fragment
之間的通信LifecycleOwner
: Activity/Fragment
都是LifecycleOwner
(support包下的AppCompatActivity和對應的Fragment),他是androidx.lifecycle:lifecycle-common包下的一個藉口,只有getLifecycle()一個方法,返回一個Lifecycle對象Lifecycle
: 而這個Lifecycle
就是維護生命週期state的主體,默認實現是LifecycleRegistry
,這個提及來也挺長的,之後有空再新的文章裏仔細說明,反正如今讀者只要知道咱們經常使用的AppCompatActivity/Fragment
都是能夠拿到生命週期Lifecycle的就好了LifecycleObserver
: 也是一個接口,不過它一個抽象方法也沒有,若是咱們須要一個新的自定義的觀察 者,只要實現這個接口,而後在須要對應生命週期方法回調的方法上添加OnLifecycleEvent
註解並添加對應註解就行了,LiveData
有一個 LifecycleBoundObserver
內部類實現了這個接口,不過繼承關係是這樣的 LifecycleObserver
<--GenericLifecycleObserver
<- LifecycleBoundObserver
,LifecycleBoundObserver
會在onStateChange
收到回調,不依賴於註解,不過讀 者如今只要知道在Lifecycle
中state
發生改變的時候,LifecycleObserver
會收 到通知(void onStateChanged(LifecycleOwner source, Lifecycle.Event event);
)LifecycleBounderObserver
,和不帶的AlwaysActiveObserver
..abstract class LiveDate{
class LifecycleBounderObserver extends ObserverWrapper implements GenericLifecycleObserver{
}
private abstract ObserverWrapper{
}
private class AlwaysActiveObserver extends ObserverWrapper {
}
}
複製代碼
LifecycleOwner
, Observer
類(簡單的回調通知接口)LifecycleOwner
獲取Lifecycle
,判斷時候是DESTROYED
狀態,是的話直接return 將Observer
和LifecycleOwner
包裝爲LifecycleBoundObserver
對象SafeIterableMap<Observer<? super T>, ObserverWrapper>
對象mObservers,保存了Observer和對應的Wrapper,存入LifecycleBoundObserver對象後判斷是否已存在而且是否對應當前LifecycleOwner,作出相應的處理,當mObservers中沒有時,直接給LifecycleOwner的Lifecycle註冊該LifecycleBoundObservermActive
,而後經過LiveData類的mActivieCount是否爲0來判斷是否是徹底沒有通知過,若是是進入非active狀態mActiveCount就-1,不然+1,原先未active如今active了,調用onActive
方法,新的mActivieCount == 0
而且 新active的狀態爲false就調用onInactive
方法,而後判斷mActive
,true則會調用dispatchValue方法,基本上mActivieCount只會有0 -> 1 ,1 -> 0兩個狀態變化,因此onActive
是LiveData觀察者數量從無到有時回調,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);
}
}
複製代碼
} ```android
onActive
方法,反之會走onInactive
方法,無論原先狀態如何,只要新狀態是活躍就會走dispatchValue
onInactive/onActive
是LiveData
裏兩個open protected的方法,只在MediatorLiveData裏有實現,我尚未仔細研究MediatorLiveData,你們能夠去看看源碼LiveData
的dispatchValue
方法,傳入的參數爲ObserverWrapper
,也就是LifecycleBoundObserver的父類(LifecycleBoundObserver
繼承了ObserverWrapper
,實現了GenericLifecycleObserver
),在這要注意下內部類(非靜態)是能夠拿到外部類實例的,LiveData.this.XXX,忘記的同窗複習下,我是很久沒用java,忽然看到有點懵逼..//傳入參數是Observer,有的話就分發給它,爲null就對全部Observers分發數據
void dispatchingValue(@Nullable 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());
//標記爲無效時會跳出循環,在while循環中等待一次mDispatchInvalidated再次變爲true時再次進入for循環
if (mDispatchInvalidated) {
break;
}
}
}
//沒有被標記無效時while循環就執行一次完事,不然會再次執行
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
複製代碼
LiveData
中的mDispatchingValue/mDispatchInvalidated
在此處保證不會重複分發或者分發舊的value,當setValue
分發調用dispatchValue(null)
時會遍歷全部的Observer分發新值,不然只分發給傳入的ObserverWrapper
,這裏說明下:LiveData
維護了mDispatchingValue/mDispatchInvalidated
,而Observer可能會有多個,都持有LiveData對象(由於是內部類),因此等待的observer對應的LiveData
會得到mDispatchInvalidated = true
,中斷進行中的分發,讓舊數據再也不分發considerNotify
: 第一步檢查ObserverWrapper
是否mActive
,第二步檢查shouldBeActive()
,第三步檢查ObserverWrapper
的版本observer.mLastVersion >= mVersion
,最後才通知更新,調用Observer的onChange方法ObserverWrapper
中的mActive
用來控制該觀察者是否須要分發(activeStateChanged(boolean)
方法的做用下)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);
}
複製代碼
很簡單的邏輯,就是
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
複製代碼
mActive會在生命週期變化時會被屢次檢查
2. 第二步再次檢查`shouldBeActive()`狀態
3. 第三步檢查`mLastVersion`和`mVersion`
這個version是在setValue時被+1的,檢查一下防止重複分發,完成後修改lastVersion而後回調`onChange(T)`
複製代碼
按慣例先看看代碼,postValue的代碼也好理解,只是給賦值操做加了一個鎖,並把setValue放到主線程執行,使多個postValue只有最後一個的value生效api
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
裏都執行了postValue傳入不一樣的值A,B,先會在方法內的mDataLock鎖住的代碼塊競爭執行,好比A先執行,mPendingData
先被賦值爲A,postTask
=> true,而後賦值爲B,也就是說第一次的賦值纔會經過同步塊以後的if判斷,執行分發runnable,線程T-B
只是修改了mPendingValue
的值app
而後會有一個主線程上的同步代碼塊(也是同一個鎖),將新值執行setValue
,mPendingValue
重設爲初始值,也就是說取得值其實是後一個線程的B,後面分發完成重設爲NOT_SET
,後面的PostValue又進入原來的邏輯了ide
postValue的註釋也很清楚了: If you called this method multiple times before a main thread executed a posted task, only the last value would be dispatched.工具
LiveData的結構是比較簡單的,使用時注意不要屢次註冊觀察者,通常若是在Activity中使用,就在OnCreate方法註冊,Activity被關閉或回收後觀察者會自動解除訂閱,因此不會發生泄漏,咱們也能夠本身繼承LiveData作更多的定製來實現本身的業務邏輯,配合Tranformations工具類和MediatorLiveData能夠實現不少比較複雜的邏輯post