目錄
前言
Android應用開發(fā)的一大問題就是架構缺失,至少我觀察到的是這樣的。我覺得不能苛責說這是程序員水平的問題,Android本身也有它的問題。Android誕生已經超過十年了,但是Android平臺并沒有給我們提供一種簡單明了易用的方案,來解決代碼放哪這么一個基本的問題。所以,造成的結果就是不知道放哪那就往四大組件里面堆吧,堆得太多了,那就寫個Util類吧,僅此而已。
Google估計也是發(fā)現(xiàn)了這種問題,在2017年推出了官方架構,AAC。雖然說有些晚,但是效果還是很顯著的,讓Android應用開發(fā)一下子從刀耕火種的原始社會,直接來到了現(xiàn)代化社會。不得不說,Google一出手,就知道有沒有。Google I/O 2019上公布的數(shù)據(jù)說,Google Play上的Top 1000應用中有80%采用了AAC架構。足可見AAC的受歡迎程度。
問題
數(shù)據(jù)是如何傳輸?shù)氖侨魏渭軜嫷年P鍵環(huán)節(jié),而AAC架構的數(shù)據(jù)傳輸就是依靠LiveData。LiveData可謂是為Android量身定做的數(shù)據(jù)傳輸方案,它不僅解決了數(shù)據(jù)如何傳輸?shù)膯栴},又解決了Android平臺生命周期復雜性的問題。LiveData“神奇”的一點就在于它是可感知生命周期的,onStart之后觀察者才會被通知,onDestroy的時候觀察者又會被自動移除,最大程度上避免了null指針和內存泄漏。這就是我們要在LiveData源碼中尋找的答案,這一切是怎么實現(xiàn)的。(源碼版本androidx.lifecycle:lifecycle-livedata:2.2.0)
1. LiveData的職責
LiveData應該完成哪些職責呢?無外這幾點:
- 添加包含LifecycleOwner的觀察者
- 在LifecycleOwner的ON_DESTROY事件時,移除觀察者
- LiveData的數(shù)據(jù)變化后,是否通知觀察者(觀察者可能未處于STARTED或者RESUMED狀態(tài))
- 生命周期狀態(tài)變化時,是否通知觀察者(可能此時生命周期來到了STARTED或者RESUMED狀態(tài),之前又積壓了未通知的數(shù)據(jù))
- 通知觀察者,并且避免重復通知
LiveData源碼的主要內容就是處理這些問題。
2. LiveData添加觀察者
為LiveData添加帶LifecycleOwner的觀察者的方式特別簡單,調用其observe方法即可:
public abstract class LiveData<T> {
/**
* LiveData的觀察者集合,以鍵值對的形式被添加進去,
* 原始觀察者Observer是鍵,對Observer的包裝類ObserverWrapper是值。
* SafeIterableMap是支持庫內部實現(xiàn)的一種數(shù)據(jù)結構,底部以鏈表實現(xiàn),表面上看上去卻像個Map
*/
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
//如果Lifecycle已經處于DESTROYED狀態(tài),直接返回
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//對我們提供的observer進行包裝,看包裝類的名字 LifecycleBoundObserver 就知道,
// 要包裝成一個跟生命周期關聯(lián)的觀察者類
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//mObservers是LiveData觀察者的集合
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//不允許相同的owner,observer組合重復添加
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//我們的包裝類LifecycleBoundObserver還是LifecycleEventObserver
//它也被添加到了Lifecycle的觀察者中
owner.getLifecycle().addObserver(wrapper);
}
}
//LiveData觀察者的定義
public interface Observer<T> {
void onChanged(T t);
}
代碼不多,包含的東西不少。我們提供的觀察者observer,在被包裝之后,既被添加到了LiveData的觀察者集合中,又被添加到了了Lifecycle的觀察者集合中。這至少保證了兩件事:第一,LiveData的數(shù)據(jù)變化后,observer可以收到通知;第二,生命周期狀態(tài)變化時,observer可以收到通知。即LiveData職責的第3、第4兩點。
LiveData本身定義的觀察者Observer是很簡單的,只有一個onChanged方法,在LiveData數(shù)據(jù)發(fā)生變化時被調用。但是,如前所述,LiveData最大的特點就是,它與生命周期的緊密關聯(lián)。其observe方法包含兩個參數(shù),LifecycleOwner和Observer,每個Observer還附帶了一個生命周期的擁有者LifecycleOwner。為了完成前面說的職責3和職責4,需要對Observer進行包裝,以為其增加更多狀態(tài),所以才有了ObserverWrapper,LifecycleBoundObserver。
public abstract class LiveData<T> {
static final int START_VERSION = -1;
//有多少LiveData的觀察者處于“活動”狀態(tài)
int mActiveCount = 0;
private abstract class ObserverWrapper {
//被包裝者,即LiveData原始的觀察者
final Observer<? super T> mObserver;
//觀察者是否處于“活動”狀態(tài);為原始觀察者mObserver增加屬性,這也是包裝類的意義
boolean mActive;
//每個ObserverWrapper初始時version都被設置為了START_VERSION
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
/**
* ObserverWrapper的主要職責就是:接收來自外部的activeState狀態(tài)的變化,
* 這里的activeState指的是被包裝者 mObserver 是否處于“活動”狀態(tài)
* 處于“活動”狀態(tài)的觀察者可以接收LiveData數(shù)據(jù)的變化,否則則不能;
* 以上所說的活動狀態(tài)指的是當前觀察者的活動狀態(tài),可以理解為 mObserver 的活動狀態(tài),
* LiveData本身也有活動狀態(tài),當LiveData從“活動”狀態(tài)變?yōu)椤胺腔顒印睜顟B(tài)時,其onActive方法會被調用;
* 當LiveData從“非活動”狀態(tài)變?yōu)椤盎顒印睜顟B(tài)時,其onInactive方法會被調用;
* LiveData的活動狀態(tài)取決于它本身的觀察者是否至少有一個處于“活動”狀態(tài)
*/
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處于活動的觀察者計數(shù)
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive(); //LiveData中的方法,空實現(xiàn)
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive(); //LiveData中的方法,空實現(xiàn)
}
if (mActive) {
//LiveData中的方法,每當觀察者來的“活動”狀態(tài)時,就會分發(fā)LiveData中的數(shù)據(jù),
//至于observer中的onChanged方法會不會被調用,還有別的判斷,之后再看
dispatchingValue(this);
}
}
}
}
ObserverWrapper的主要職責是處理活動狀態(tài)的變化,這種活動狀態(tài)包括觀察者的活動狀態(tài),和LiveData的活動狀態(tài)(注意區(qū)分兩者)。
在本文中,活動狀態(tài)指的是一種狀態(tài),有兩種情況,“活動”和“非活動”;“活動”狀態(tài)指的是前述狀態(tài)處于“活動”這種情況。
需要注意,activeStateChanged方法是在外部被調用的,也就是說,有地方監(jiān)聽狀態(tài)的變化,并負責通知ObserverWrapper,我們之后會看到。
再來看看對ObserverWrapper進一步的包裝LifecycleBoundObserver:
public abstract class LiveData<T> {
/**
* 很重要的一點LifecycleBoundObserver實現(xiàn)了LifecycleEventObserver接口,
* 這個接口是對于生命周期事件的觀察者,詳見Lifcycle源碼解析
*/
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
//生命周期至少處于STARTED狀態(tài)時,觀察者才是“活動”狀態(tài)
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//該方法是接口LifecycleEventObserver中的方法
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//生命周期來到了DESTROYED,則從LiveData中移除原始的觀察者mObserver
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
//指的是LiveData中的removeObserver方法
//removeObserver方法會把觀察者從LiveData的觀察者集合中移除,
//然后還會調用下面的detachObserver方法,從Lifecycle中移除觀察者
removeObserver(mObserver);
return;
}
//上面提到的ObserverWrapper中的activeStateChanged方法,
//每當生命周期變化時就調用activeStateChanged
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
//從生命周期觀察者中移除
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
}
先來回顧一下子為LiveData添加一個觀察者的流程,我們的觀察者Observer被包裝成了LifecycleBoundObserver,然后分別被添加到了LiveData的觀察者集合中,和Lifecycle的觀察者中。LifecycleBoundObserver背后其實是兩層包裝,第一層包裝是ObserverWrapper(可以被添加到LiveData的觀察者中),第二層包裝是LifecycleBoundObserver(實現(xiàn)了LifecycleEventObserver,可以被添加到Lifecycle的觀察者中)。

然后再來看LifecycleBoundObserver的源碼,注釋中已經寫得很清楚了,主要就時兩點:
- 生命周期變化時通知活動狀態(tài)是否處于“活動”中(處于“活動”狀態(tài)的觀察者,并且之前有“積壓”的數(shù)據(jù)未通知時,觀察者的
onChanged方法會被調用) - 生命周期來到DESTROYED時,移除相應觀察者(從LiveData和Lifecycle中)
總結一下,LiveData添加觀察者的內容:
- 對Observer進行包裝
- 將包裝后的Observer分別添加到LiveData和Lifecycle的觀察者中
- 將生命周期的變化轉換為活動狀態(tài)的變化,并且通知觀察者(ObserverWrapper)活動狀態(tài)的變化
- 生命周期來到DESTROYED時,移除相應觀察者(從LiveData和Lifecycle中)
LiveData職責的1、2、4條都得到了驗證。下面主要來看LiveData是如何通知觀察者數(shù)據(jù)改變的,并且如何避免重復的通知。也即,LiveData職責的第3、第5兩條。
3. LiveData數(shù)據(jù)的通知
LiveData需要在兩種情況下分發(fā)數(shù)據(jù):
- LiveData本身數(shù)據(jù)發(fā)生變化時
- 某個觀察者由于生命周期的變化而變成“活動”狀態(tài)時
之所以講分發(fā)數(shù)據(jù),而不是通知數(shù)據(jù)的變化,是因為真正的通知數(shù)據(jù)的變化還取決于其他因素,例如,觀察者是否處于“活動”狀態(tài),觀察者是否已經接收過本次的數(shù)據(jù)。
改變LiveData的數(shù)據(jù)需要使用其setValue或者postValue方法,取決于是否在主線程修改數(shù)據(jù):
public abstract class LiveData<T> {
//數(shù)據(jù)鎖
final Object mDataLock = new Object();
static final int START_VERSION = -1;
//初始時下LiveData處于未設置狀態(tài)
static final Object NOT_SET = new Object();
//LiveData真正的Data,LiveData的數(shù)據(jù)
private volatile Object mData;
//通過postValue設置數(shù)據(jù)
volatile Object mPendingData = NOT_SET;
//LiveData的數(shù)據(jù)version,用于與觀察者的version進行比較,避免重復通知
private int mVersion;
private boolean mDispatchingValue;
private boolean mDispatchInvalidated;
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
/**
* 使用給定value對LiveData初始化
*/
public LiveData(T value) {
mData = value;
mVersion = START_VERSION + 1;
}
/**
* 默認初始化
*/
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
//切換到主線程去設置數(shù)據(jù),ArchTaskExecutor是AAC中使用的線程池,Room也在使用
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
//version增加
mVersion++;
mData = value;
//分發(fā)數(shù)據(jù)的變化
dispatchingValue(null);
}
}
可以看出postValue方法最終還是調用的setValue方法,setValue方法也很簡單,增加版本號,設置數(shù)據(jù),并且分發(fā)數(shù)據(jù)。
我們來跟進一下dispatchingValue方法:
public abstract class LiveData<T> {
//initiator如果為null,證明是LiveData的數(shù)據(jù)發(fā)生了變化,要對所有觀察者分發(fā)數(shù)據(jù),
//如果initiator不為null,那說明是因為這個initiator代表的觀察者變?yōu)椤盎顒印睜顟B(tài),只需要通知這個initiator本身就可以了
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//mDispatchingValue和mDispatchInvalidated兩個標志是為了防止在數(shù)據(jù)分發(fā)的時候,LiveData的數(shù)據(jù)再次發(fā)生變化;
//例如,某個觀察者onChanged方法內部又調用了setValue方法
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator); //只通知initiator本身
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) { //非“活動”狀態(tài)的observer不通知數(shù)據(jù)的變化
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;
}
//觀察者的version不小于LiveData的version,說明該觀察者已經被通知過了,不再通知
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//終于看到了我們observer的onChanged方法被調用
observer.mObserver.onChanged((T) mData);
}
}
LiveData數(shù)據(jù)分發(fā)的脈絡還是很清晰的,因為LiveData數(shù)據(jù)發(fā)生變化的,對所有觀察者考慮是否通知數(shù)據(jù)的變化;因為某個觀察者變?yōu)椤盎顒印睜顟B(tài)的,只對該觀察者本身考慮是否通知數(shù)據(jù)的變化。并且通過比較LiveData和觀察者(ObserverWrapper)的版本號,來避免重復的通知。LiveData職責的第3、第5兩條也得到了驗證。
到這里,關于LiveData的源碼基本上是分析完了,其中省略了如下一些內容:
- LiveData移除觀察者
- 為LiveData添加“永久”的觀察者(
observeForever方法),說是“永久”的觀察者,其實就是沒有綁定生命周期的觀察者,也可以手動移除。 - MutableLiveData
這些內容比較簡單,在此略過。
4. LiveData的轉換Transformations
上文提到了LiveData的onActive和onInactive方法,分別在LiveData變?yōu)椤盎顒印焙妥優(yōu)椤胺腔顒印睍r被調用,但是在LiveData本身的實現(xiàn)中,onActive和onInactive均為空實現(xiàn)。其實,單對于觀察LiveData數(shù)據(jù)的變化而言,確實沒有必要實現(xiàn)LiveData本身的活動狀態(tài)的變化,這兩個方法主要是用來自定義LiveData或者對LiveData進行轉換的。具體使用場景見Google文檔。下面具體分析一下LiveData的轉換。
最簡單的LiveData的轉換的例子就是map,就像RxJava中的map那樣。LiveData實現(xiàn)轉換的關鍵是MediatorLiveData類:
//類如其名,中介者LiveData
public class MediatorLiveData<T> extends MutableLiveData<T> {
private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
/**
* 添加作為“源”的LiveData,和對“源”的LiveData的觀察者
* 當“源”LiveData數(shù)據(jù)變化,并且當前MediatorLiveData處于“活動”狀態(tài)(擁有“活動”觀察者)時,onChanged就會被調用
* 實際上正如類名一樣,這實際上起到了中介者的作用,MediatorLiveData傳遞了“源”LiveData的數(shù)據(jù)變化,同時我們又可以在onChanged中對“源”LiveData的數(shù)據(jù)進行轉換
*/
@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
*/
@MainThread
public <S> void removeSource(@NonNull LiveData<S> toRemote) {
Source<?> source = mSources.remove(toRemote);
if (source != null) {
source.unplug();
}
}
@CallSuper
@Override
protected void onActive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().plug();
}
}
@CallSuper
@Override
protected void onInactive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().unplug();
}
}
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);
}
}
}
}
單看MediatorLiveData可能比較懵逼,沒事,結合map等轉換一起看就明白什么意思了。
public class Transformations {
private Transformations() {
}
/**
* 最簡單明了的轉換操作
* 傳入source “源”LiveData,將其轉換為另一種類型的LiveData
* LiveData<X> -> LiveData<Y>
*/
@MainThread
@NonNull
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) {
//source的變化會通知到這個方法,我們用mapFunction對我們接收到的數(shù)據(jù)進行轉換
result.setValue(mapFunction.apply(x));
}
});
//返回中介 MediatorLiveData
return result;
}
/**
* 這個方法比較不好理解,可以去看源碼中的注釋幫助理解
*/
@MainThread
@NonNull
public static <X, Y> LiveData<Y> switchMap(
@NonNull LiveData<X> source,
@NonNull final Function<X, LiveData<Y>> switchMapFunction) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
LiveData<Y> mSource;
@Override
public void onChanged(@Nullable X x) {
LiveData<Y> newLiveData = switchMapFunction.apply(x);
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
result.removeSource(mSource);
}
mSource = newLiveData;
if (mSource != null) {
result.addSource(mSource, new Observer<Y>() {
@Override
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}
/**
* 直到source數(shù)據(jù)跟上次的數(shù)據(jù)不同時才通知
*/
@MainThread
@NonNull
public static <X> LiveData<X> distinctUntilChanged(@NonNull LiveData<X> source) {
final MediatorLiveData<X> outputLiveData = new MediatorLiveData<>();
outputLiveData.addSource(source, new Observer<X>() {
boolean mFirstTime = true;
@Override
public void onChanged(X currentValue) {
final X previousValue = outputLiveData.getValue();
if (mFirstTime
|| (previousValue == null && currentValue != null)
|| (previousValue != null && !previousValue.equals(currentValue))) {
mFirstTime = false;
outputLiveData.setValue(currentValue);
}
}
});
return outputLiveData;
}
}
最初的Transformations類只有map這一個方法,現(xiàn)在又增加了兩個,源碼也不難理解,核心思想都是拿到“源”LiveData的數(shù)據(jù),然后對數(shù)據(jù)做轉換后,再設置給MediatorLiveData,這樣通過MediatorLiveData,轉換就完成了。

可以看出,LiveData是想模仿RxJava那樣的操作符的,但是,LiveData的設計思想跟RxJava差別還是很大的,能實現(xiàn)的操作符非常有限。Transformations的主要作用是,正確傳遞“源”LiveData的數(shù)據(jù)變化,并且保證觀察者的生命周期變化能傳遞給“源”LiveData。說白了,就是讓MediatorLiveData沒有存在感。
5. 隱藏技能
- 如果我們的觀察者處于“非活動”狀態(tài),他變?yōu)椤盎顒印睜顟B(tài)后只會收到最新的數(shù)據(jù),也就是說LiveData的數(shù)據(jù)是會“折疊”的。
- 除非你人為的去設置LiveData的數(shù)據(jù)為null(
setValue(null)或者postValue(null)),否則在Observer的onChanged方法中接收到的數(shù)據(jù)是不可能為null的。如果使用第三方庫提供的某些LiveData,在onChanged中判空是有必要的,說不定它用null代表什么特殊的含義。
6. 總結
我們的觀察者經過包裝后,被添加進LiveData的觀察者集合,同時,也被添加到了我們提供的Lifecycle的觀察者集合中(如果我們提供了LifecycleOwner的話),這樣,無論是LiveData本身的數(shù)據(jù)發(fā)生變化,還是觀察者變?yōu)椤盎顒印睜顟B(tài)時,我們的觀察者都會被cue到。但是,只有當我們的觀察者處于“活動”狀態(tài)并且沒有被通知過的時候(version低于LiveData的version),Observer的onChanged方法才會被調用。