1. 背景
上一篇我們分析了
Lifecycles
組件的源碼,本篇我們將繼續分析LiveData
組件
相關係列文章:
1. Jetpack源碼解析—看完你就知道Navigation是什麼了?
2. Jetpack源碼解析—Navigation爲什麼切換Fragment會重繪?
3. Jetpack源碼解析—用Lifecycles管理生命週期
2. 基礎
2.1 簡介
LiveData
是一個可觀察的數據持有者類,與常規observable
不同,LiveData
是生命週期感知的,這意味着它尊重其他應用程序組件的生命週期,例如Activity
,Fragment
或Service
。此感知確保LiveData
僅更新處於活動生命週期狀態的應用程序組件觀察者。
2.2 優點
1. 確保UI符合數據狀態
LiveData遵循觀察者模式。 當生命週期狀態改變時,LiveData會向Observer發出通知。 您可以把更新UI的代碼合併在這些Observer對象中。不必去考慮導致數據變化的各個時機,每次數據有變化,Observer都會去更新UI。
2. 沒有內存泄漏
Observer會綁定具有生命週期的對象,並在這個綁定的對象被銷燬後自行清理。
3. 不會因停止Activity而發生崩潰
如果Observer的生命週期處於非活躍狀態,例如在後退堆棧中的Activity,就不會收到任何LiveData事件的通知。
4.不需要手動處理生命週期
UI組件只需要去觀察相關數據,不需要手動去停止或恢復觀察。LiveData會進行自動管理這些事情,因爲在觀察時,它會感知到相應組件的生命週期變化。
5. 始終保持最新的數據
如果一個對象的生命週期變到非活躍狀態,它將在再次變爲活躍狀態時接收最新的數據。 例如,後臺Activity在返回到前臺後立即收到最新數據。
6. 正確應對配置更改
如果一個Activity或Fragment由於配置更改(如設備旋轉)而重新創建,它會立即收到最新的可用數據。
7.共享資源
您可以使用單例模式擴展LiveData對象幷包裝成系統服務,以便在應用程序中進行共享。LiveData對象一旦連接到系統服務,任何需要該資源的Observer都只需觀察這個LiveData對象。
2.3 基本使用
在我們的Jetpack_Note中有使用demo,具體可查看LiveDataFragment。
Demo中通過對一個LiveData對象進行生命週期的監聽,實現將值打印在控制檯中。首先聲明一個LiveData對象:
private lateinit var liveData: MutableLiveData<String>
點擊開始觀察數據按鈕,彈出控制檯,我們可以看到控制檯輸出了onStart()
日誌,因爲我們將liveData的值和Fragment的生命週期進行了綁定,當返回桌面或者銷燬Fragment的時候,LiveData的值會變成相應的生命週期函數,並打印在控制檯中:
class LiveDataFragment : Fragment() {
private lateinit var liveData: MutableLiveData<String>
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_live_data, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
liveData = MutableLiveData()
btn_observer_data.setOnClickListener {
if (FloatWindow.get() == null) {
FloatWindowUtils.init(activity?.application!!)
}
FloatWindowUtils.show()
//創建一個觀察者去更新UI
val statusObserver = Observer<String> { lifeStatus ->
FloatWindowUtils.addViewContent("LiveData-onChanged: $lifeStatus")
}
liveData.observeForever(statusObserver)
}
}
override fun onStart() {
super.onStart()
liveData.value = "onStart()"
}
override fun onPause() {
super.onPause()
liveData.value = "onPause()"
}
override fun onStop() {
super.onStop()
liveData.value = "onStop()"
}
override fun onDestroy() {
super.onDestroy()
liveData.value = "onDestroy()"
}
}
**注意:**這裏我使用了
observeForever
監聽了所有生命週期方法,所以你會看到onDestroy()等生命週期函數的打印。
好了,Demo很簡單,接下來我們來看一下源碼,進行分析:
3. 源碼分析:
3.1 observer()
我們聲明瞭一個LiveData
對象,並通過監聽Fragment
的生命週期來改變LiveData
中的value值,LiveData
實際上就像一個容器,Demo中存儲了一個String類型的值,當這個值發生改變的時候,可以在回調中監聽到他的改變。接下來我們就先從addObserver
入手:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
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);
}
查看源碼,我們調用observer()
時,傳遞了兩個參數,第一個是LifecycleOwner
接口實例,而我們繼承的Fragment
本身就已經實現了這個接口,所以我們傳this
即可;第二個參數Observer
就是我們觀察的回調。接下來將這兩個參數傳遞new出了一個新的對象:LifecycleBoundObserver
,最後將LifecycleBoundObserver
和LifecycleOwner
進行了綁定,其實這裏面我們可以將LifecycleOwner
就理解成我們的Fragment
或者Activity
的實例,因爲它們都實現了LifecycleOwner
。
3.2 LifecycleBoundObserver
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
.....
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//Activity生命週期變化時,回調方法
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
//更新livedata活躍狀態
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
//解除監聽
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
我們可以看到這裏面與LifecycleOwner
進行了綁定,並且實現了onStateChanged
方法,當生命週期發生變化時執行activeStateChanged(shouldBeActive());
方法;shouldBeActive()
返回了 要求生命週期至少是STARTED狀態才被認爲是activie狀態;如果state是DESTROYED
狀態時,解綁LifecycleOwner
和LiveData
。接下來我們看下怎樣更新livedata中數據值:
3.3 dispatchingValue()
我們追蹤activeStateChanged
方法發現,在裏面做了一些活躍狀態值的操作,並且當狀態活躍時,更新數據值:
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);
}
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
...
//遍歷LiveData的所有觀察者執行下面代碼
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
...
}
//將數據值回調到livedata.observer()回去
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);
}
從上面我們可以看到LiveData
的數據更新以及數據回調的整個過程,但是當我們手動setValue()
的時候過程是怎樣的呢?你會發現,setValue()
其實最後就是通過調用了dispatchingValue()
方法。而關於postValue()
在子線程更新數據的相關代碼,這裏就不做介紹了,其實你大可以想出來,就是使用的Handler
。
LiveData
中的代碼很簡潔,400多行的代碼,看起來也並不費勁,下面我們來分析下整個流程:
- 通過使用
LiveData
對象,爲它創建觀察者Observer
- 創建
Observer
時綁定Fragment
生命週期 LifecycleBoundObserver
生命週期變化時,dispatchValue
下發更新LiveData
中的值- 當
LiveData
主動setValue
時,會主動dispatchValue
,並且會considerNotify
激活observer
4. 擴展
4.1 Map轉換
我們在開發中經常會遇到這種場景,有時我們需要根據另外一個LiveData
實例返不同的LiveData
實例,然後在分發給Observer
,Lifecycle
包提供了Transformations
類,可以幫助我們實現這樣的場景:
通過**Transformations.map()**使用一個函數來轉換存儲在 LiveData
對象中的值,並向下傳遞轉換後的值:
LiveDataViewModel
class LiveDataViewModel : ViewModel() {
val data = listOf(User(0,"Hankkin"), User(1,"Tony"),User(2,"Bob"),User(3,"Lucy"))
val id = MutableLiveData<Int>()
//map轉換返回User實體
val bean: LiveData<User> = Transformations.map(id, Function {
return@Function findUserById(id.value!!)
})
//根據id查找User
private fun findUserById(id: Int): User? {
return data.find { it.id == id }
}
}
LiveDataFragment
//改變ViewModel中idLiveData中的值
btn_observer_map.setOnClickListener {
mId++
viewModel.id.postValue(mId)
}
//當idLiveData變化後,UserBean也會改變且更新Textview的文本
viewModel.bean.observe(
this,
Observer { tv_livedata_map.text = if (it == null) "未查找到User" else "爲你查找到的User爲:${it.name}" })
4.2 Map源碼
@MainThread
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;
}
我們可以看到map
的源碼是通過MediatorLiveData
中的addSource()
方法來實現的,第一個參數爲我們需要改變的LiveData
值,也就是我們上面例子中的userid
,第二個參數則是我們傳過來的Fuction
通過高階函數,將值set到LiveData上。
下面我們看下addSource()
方法:
@MainThread
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()) {
e.plug();
}
}
這裏把我們的LiveData和Observer封裝成了Source對象,並且這個對象,不能重複添加,具體代碼可查看Source
:
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);
}
void unplug() {
mLiveData.removeObserver(this);
}
@Override
public void onChanged(@Nullable V v) {
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
mObserver.onChanged(v);
}
}
}
首先Source是一個觀察者,可以看到,我們外部使用的Observer會以Source的成員變量的形式,添加到傳入的LiveData中。值得注意的是,這裏使用了mLiveData.observeForever(this);
。
從observeForever()
用法可以看到,我們並沒有傳遞LifecycleOwner
,因此它並不具備生命感知能力。從註釋中也可見一斑:This means that the given observer will receive all events and will never be automatically removed.
map()的原理就是基於MediatorLiveData,MediatorLiveData內部會將傳遞進來的LiveData和Observer封裝成內部類,然後放在內部維護的一個Map中。並且自動幫我們完成
observeForever
()和removeObserver()
。
5.總結
LiveData
基於觀察者模式實現,並且和LifecycleOwner
進行綁定,而LifecycleOwner
又被Fragment
和Activity實現,所以它可以感知生命週期;在當前的LifecycleOwner不處於活動狀態(例如onPasue()
、onStop()
)時,LiveData是不會回調observe()
的,因爲沒有意義.- 同時
LiveData
只會在LifecycleOwner
處於Active
的狀態下通知數據改變,果數據改變發生在非 active 狀態,數據會變化,但是不發送通知,等owner
回到 active 的狀態下,再發送通知; LiveData
在DESTROYED時會移除Observer
,取消訂閱,不會出現內存泄漏postValue
在異步線程,setValue
在主線程- 如果
LiveData
沒有被observe()
,那麼此時你調用這個LiveData的postValue(…)/value=…,是沒有任何作用
當然官方推薦我們LiveData
配合ViewModel
一起使用,因爲LiveData
一般都出現在ViewModel
中,所以我們下篇文章會繼續分析ViewModel
.