LiveData是什么?
在官網(wǎng)以及網(wǎng)上有很多文章都會(huì)介紹LiveData是什么、能夠滿足什么場景以及優(yōu)勢。假若用一句話概括,它就是與EventBus有著類似功能的一個(gè)庫--事件發(fā)布訂閱機(jī)制。那么今天我們就來扒一扒它是如何實(shí)現(xiàn)的。本文將會(huì)以4個(gè)方面進(jìn)行源碼分析:
-
LiveData是如何感知生命周期的? - 發(fā)布者發(fā)送數(shù)據(jù)后,訂閱者是如何收到的?
- 粘性數(shù)據(jù)是如何產(chǎn)生的以及如何避免?
- 它與
EventBus有什么區(qū)別?
簡單使用
- 添加依賴
implementation "androidx.lifecycle:lifecycle-livedata:2.3.0"
- 簡單demo
public class MainActivity extends AppCompatActivity {
private MutableLiveData<String> mLiveData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 第一步
mLiveData = new MutableLiveData<>();
// 第二步
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
// 第四步
Log.e("MainActivity", s);
}
});
}
public void jump(View view) {
// 第三步
mLiveData.setValue("Hello");
}
}
LiveData的使用非常簡單,執(zhí)行代碼中的三個(gè)步聚,第四步就可以收到發(fā)送過來的信息。接下來分析每一步都做了一些什么事。
源碼分析
- 構(gòu)造
LiveData對(duì)象
// MutableLiveData.java
public MutableLiveData() {
super();
}
// LiveData.java
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
LiveData是一個(gè)抽象類,我們創(chuàng)建的MutableLiveData是它的實(shí)現(xiàn)類。在父類的構(gòu)造方法中,初始化了兩個(gè)屬性,一個(gè)是Object類型的mData字段,它的作用是用來保存我們通過setValue傳過來的值。另一個(gè)是int類型的mVersion字段,它的初始值為0。它有什么用呢?這里暫且先埋個(gè)坑。
-
observe方法
// LiveData.java
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
// owner就是我們傳過來的MainActivity,很顯然State不可能為DESTROYED
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
// 注釋1
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// 注釋2
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;
}
// 注釋3
owner.getLifecycle().addObserver(wrapper);
}
先看注釋1部分
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
將我們的生命周期擁有者,也就是我們的MainActivity和我們在MainActivity創(chuàng)建出來的觀察者Observer包裝成了LifecycleBoundObserver,我們來看看其構(gòu)造方法做了什么事。
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
自己保存著我們的MainActivity的引用,調(diào)用父類ObserverWrapper構(gòu)造方法,保存我們創(chuàng)建的Observer對(duì)象。在父類里面還有一個(gè)比較重要的int類型的屬性: mLastVersion。上面有提到過mVersion字段,現(xiàn)在又來一個(gè)mLastVerison,猜測一下這兩個(gè)字段是用來判斷當(dāng)前和上一次的版本,那具體是用來判斷什么的呢?
再來看注釋2部分
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
以我們創(chuàng)建的Observer作為key,包裝對(duì)象作為value添加到mObservers集合中,被保存到Map集合中的value還會(huì)被維護(hù)成雙向鏈表。
public V putIfAbsent(@NonNull K key, @NonNull V v) {
Entry<K, V> entry = get(key);
if (entry != null) {
return entry.mValue;
}
put(key, v);
return null;
}
protected Entry<K, V> put(@NonNull K key, @NonNull V v) {
Entry<K, V> newEntry = new Entry<>(key, v);
mSize++;
if (mEnd == null) {
mStart = newEntry;
mEnd = mStart;
return newEntry;
}
mEnd.mNext = newEntry;
newEntry.mPrevious = mEnd;
mEnd = newEntry;
return newEntry;
}
再來看注釋3部分
// 這行代碼就使得LiveData可以感知Activity的生命周期
owner.getLifecycle().addObserver(wrapper);
看到這里就明白了LiveData是如何感知Activity的生命周期了。將LifecycleBoundObserver作為生命周期的觀察者,這樣在生命周其變化時(shí)就會(huì)回調(diào)到onStateChanged方法。addObserver方法源碼分析可以看手撕Jetpack組件之Lifecycle。
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() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
...
}
setValue
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
記得在上文中有提到過mVersion這個(gè)字段,初始值為0,此時(shí)變成了1,我們傳的數(shù)據(jù)被mData引用。繼續(xù)跟進(jìn):
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());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
因在setValue方法中傳入的ObserverWrapper為null,所以會(huì)進(jìn)入到else條件里面去。上文有提到過生命周期持有者與我們創(chuàng)建的Observer被包裝成LifecycleBoundObserver對(duì)象,然后又以Observer為key,這個(gè)包裝對(duì)象為value添加到mObservers集合中。繼續(xù)跟進(jìn)considerNotify方法。
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.
// 注釋4
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
// 注釋5
if (observer.mLastVersion >= mVersion) {
return;
}
// 注釋6
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
先看注釋6部分,observer.mObserver指的就是我們在MainActivity里面創(chuàng)建的Observer,所以訂閱者就收到了數(shù)據(jù)。
注釋4和注釋5是用來阻止數(shù)據(jù)回調(diào)的判斷條件。先看注釋4
// LifecycleBoundObserver
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
由LifecycleOwner的狀態(tài)決定返回值,因?yàn)檫@里的mOwner就是我們的MainActivity,此時(shí)我們是在setValue的操作,狀態(tài)已經(jīng)變成RESUMED,所以這里返回true。注釋4的if語句內(nèi)不會(huì)執(zhí)行。
再看注釋5部分,這兩個(gè)屬性在上文中多次提到,原來它們的作用是用來判斷是否要回調(diào)觀察察者的回調(diào)方法。mLastVersion初始值為-1,mVersion的值在setValue時(shí)已經(jīng)變成1了,所以注釋5的條件也不成立。
到這里,整個(gè)源碼分析就已經(jīng)完畢。我們再來看看其它API的調(diào)用。
postValue
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
源碼看起來比較簡單。就是往主線程提交了一個(gè)Runnable
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
最終還是調(diào)到了setValue。這兩者的唯一區(qū)別就是setValue只能在主線程,postValue不受線程局限。
observeForever
該方法添加的Observer并不受Activity的生命周期所約束。也就是說,當(dāng)我們在Activity的onCreate方法注冊一個(gè)觀察者時(shí),若沒有在onDestroy方法中手動(dòng)移除這個(gè)觀察者,當(dāng)Activity被銷毀后,這個(gè)觀察者仍然可以收到消息的回調(diào)。它是如何做到的?來看看其源碼實(shí)現(xiàn)。
@MainThread
public void observeForever(@NonNull Observer<? super T> observer) {
assertMainThread("observeForever");
// 這里與observe方法一樣,將我們傳進(jìn)來的observer包裝成一個(gè)wrapper對(duì)象
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
// 將其放入到mObservers這個(gè)集合中
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);
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
// 看到我們上面分析過了的方法。不過這里的參數(shù)為上面的AlwaysActiveObserver
dispatchingValue(this);
}
}
由于dispatchingValue方法的參數(shù)不為空,所以會(huì)進(jìn)入這個(gè)方法的if語句中,最終就會(huì)執(zhí)行到上面提到的注釋4部分。由于我們的觀察者是被包裝了AlwaysActiveObserver對(duì)象,注釋4部分的if條件判斷語句由這個(gè)類實(shí)現(xiàn)。
@Override
boolean shouldBeActive() {
return true;
}
這里它是直接返回了true,這也就使得它在沒有被手動(dòng)移除時(shí),即使Activity銷毀了仍然可以收到消息的原因。而我們前面提到LifecycleBoundObserver,它實(shí)現(xiàn)這個(gè)方法是由當(dāng)前Activity的生命周期的State來決定的。
粘性事件
在開發(fā)中共用同一個(gè)LiveData是非常常見的,但隨之也會(huì)產(chǎn)生一個(gè)副作用,數(shù)據(jù)粘性。也就是說,新注冊一個(gè)觀察者的時(shí)候,仍然可以收到上個(gè)觀察者訂閱的數(shù)據(jù)。比如我們在A界面跳轉(zhuǎn)到B界面,在跳轉(zhuǎn)之前,先用LiveData#setValue一個(gè)值,此時(shí)在B界面的onCreate方法用同一個(gè)LiveData對(duì)象注冊一個(gè)觀察者,居然收到了上個(gè)界面發(fā)送來的數(shù)據(jù)。一般情況下,我們是不希望收到上個(gè)界面的數(shù)據(jù)的,那這產(chǎn)生的原因是什么呢?
在上文有多次提到過,LiveData有兩個(gè)比較重要的屬性:Object類型的mData和int類型的mVersion,分別記錄setValue發(fā)過來的數(shù)據(jù)和類似某種計(jì)數(shù)機(jī)制數(shù)據(jù)發(fā)送的次數(shù),每調(diào)用一次setValue,這個(gè)次數(shù)都會(huì)++。
界面AsetValue之后,此時(shí)LiveData中的mData保存著數(shù)據(jù),mVersion為1。打開界面B,因?yàn)槭窃诮缑鍮的onCreate方法內(nèi)用LiveData注冊了一個(gè)新Observer,根據(jù)上文提到LiveData感知生命周期部分,會(huì)執(zhí)行到LifecycleBoundObserver#onStateChanged方法
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() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
...
}
最終會(huì)執(zhí)行到上文提到的注釋5部分代碼。因?yàn)樵趧?chuàng)建一個(gè)新LifecycleBoundObserver時(shí),它的mLastVersion屬性值-1,所以注釋5部分的if條件語句不成立,所以就會(huì)執(zhí)行到注釋6部分。這就是收到了上一個(gè)訂閱者的數(shù)據(jù)原因。
如何避免這個(gè)問題了?
從理論上來分析,每個(gè)界面都使用自己的LiveData,每次都創(chuàng)建一個(gè)新LiveData對(duì)象。但由于在實(shí)際開發(fā)中,數(shù)據(jù)共享是非常常見的需求,所以這種方式并不是很完美。
通過上文的分析,在注釋4和注釋5這兩個(gè)條件語句任意滿足的話都可攔截訂閱者收到發(fā)布者發(fā)布的數(shù)據(jù)。根據(jù)比較,注釋5這個(gè)點(diǎn)是相對(duì)比較容易hook的。通過反射,在新注冊Observer時(shí),把其包裝對(duì)象LifecycleBoundObserver中的mLastVersion改成與當(dāng)前LiveData中的mVersion一樣的值就可以了。
思路分析:
- 想要修改
mLastVersion字段,就需要先獲取LifecycleBoundObserver字節(jié)碼對(duì)象 - 由于
LifecycleBoundObserver是被保存在集合中,所以需要先獲取mObservers字節(jié)碼對(duì)象 - 獲取
mObservers就需要先獲取LiveData的字節(jié)碼對(duì)象
public class CustomLiveData<T> extends MutableLiveData<T> {
@Override
public void observe(@NonNull @NotNull LifecycleOwner owner, @NonNull @NotNull Observer<? super T> observer) {
super.observe(owner, observer);
try {
hook((Observer<T>) observer);
} catch (Exception e) {
Log.e("CustomLiveData", "observe exception: " + e.getMessage());
}
}
private void hook(Observer<T> observer) throws Exception {
Class<LiveData> liveDataClass = LiveData.class;
Field mObserversField = liveDataClass.getDeclaredField("mObservers");
mObserversField.setAccessible(true);
Object mObservers = mObserversField.get(this);
// 因?yàn)樵贛ap中獲取value時(shí)是通過get方法獲取,所以還需要拿到這個(gè)get方法的字節(jié)碼對(duì)象
Method getMethod = mObservers.getClass().getDeclaredMethod("get", Object.class);
getMethod.setAccessible(true);
// 我們傳進(jìn)來的Observer被作為key,與LifecycleBoundObserver存入到mObservers中
Object entry = getMethod.invoke(mObservers, observer);
// LifecycleBoundObserver
Object lbo = null;
if (entry instanceof Map.Entry) {
lbo = ((Map.Entry) entry).getValue();
}
if (lbo == null) {
throw new NullPointerException("observerWrapper為空");
}
// mLastVersion是在父類中,先獲取父類ObserverWrapper字節(jié)碼對(duì)象
Class<?> observerWrapperClass = lbo.getClass().getSuperclass();
Field mLastVersionField = observerWrapperClass.getDeclaredField("mLastVersion");
mLastVersionField.setAccessible(true);
Field mVersionField = liveDataClass.getDeclaredField("mVersion");
mVersionField.setAccessible(true);
Object mVersionValue = mVersionField.get(this);
mLastVersionField.set(lbo, mVersionValue);
}
}
該解決方案參考Android消息總線的演進(jìn)之路:用LiveDataBus替代RxBus、EventBus
之前有用過美團(tuán)的這個(gè)LiveDataBus這個(gè)庫,但發(fā)現(xiàn)一個(gè)問題就是短時(shí)間內(nèi)發(fā)送多個(gè)事件給同一個(gè)Observer會(huì)出現(xiàn)只收到一個(gè)。
上面的方案使用的是反射,我們還可以使用一個(gè)包裝類來實(shí)現(xiàn)。
public class ObserverWrapper<T> implements Observer<T> {
private final StickyLiveData<T> mLiveData;
private final Observer<T> mObserver;
private final boolean isSticky;
private int mLastVersion;
public ObserverWrapper(StickyLiveData<T> stickyLiveData, Observer<T> observer, boolean isSticky) {
mLiveData = stickyLiveData;
mObserver = observer;
this.isSticky = isSticky;
mLastVersion = mLiveData.getVersion();
}
@Override
public void onChanged(T t) {
if (mLastVersion >= mLiveData.getVersion()) {
// //但如果當(dāng)前observer它是關(guān)心 黏性事件的,則給他。
if (isSticky && mLiveData.getStickyData() != null) {
mObserver.onChanged(mLiveData.getStickyData());
}
return;
}
mLastVersion = mLiveData.getVersion();
mObserver.onChanged(t);
}
}
public class StickyLiveData<T> extends LiveData<T> {
private T mStickyData;
private int mVersion = 0;
private final OnDestroyCallback mCallback;
public interface OnDestroyCallback {
void onDestroy();
}
public StickyLiveData(@NonNull OnDestroyCallback callback) {
this.mCallback = callback;
}
@Override
protected void setValue(T value) {
mVersion++;
super.setValue(value);
}
@Override
protected void postValue(T value) {
mVersion++;
super.postValue(value);
}
public void setStickyData(T stickyData) {
this.mStickyData = stickyData;
setValue(stickyData);
}
public void postStickyData(T stickyData) {
this.mStickyData = stickyData;
postValue(stickyData);
}
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
observeSticky(owner, observer, false);
}
public void observeSticky(LifecycleOwner owner, Observer<? super T> observer, boolean isSticky) {
super.observe(owner, new ObserverWrapper(this, observer, isSticky));
owner.getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
mCallback.onDestroy();
}
}
});
}
public T getStickyData() {
return mStickyData;
}
public int getVersion() {
return mVersion;
}
}
public class LiveDataBus {
private final ConcurrentHashMap<String, StickyLiveData> mHashMap = new ConcurrentHashMap<>();
private static final SingletonHelper<LiveDataBus> INSTANCE =
new SingletonHelper<LiveDataBus>() {
@Override
protected LiveDataBus create() {
return new LiveDataBus();
}
};
public static LiveDataBus get() {
return INSTANCE.get();
}
public <T> StickyLiveData<T> with(String eventName) {
StickyLiveData liveData = mHashMap.get(eventName);
if (liveData == null) {
liveData = new StickyLiveData<>(new StickyLiveData.OnDestroyCallback() {
@Override
public void onDestroy() {
mHashMap.remove(eventName);
}
});
mHashMap.put(eventName, liveData);
}
return liveData;
}
}
public abstract class SingletonHelper<T> {
public SingletonHelper() {
}
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
這個(gè)庫 UnPeek-LiveData也是處理LiveData粘性事件的,有興趣的也可以去查看。
與EventBus的區(qū)別
-
LiveData可以自動(dòng)感知Activity/Fragment的生命周期,EventBus做不到。 -
EventBus需要手動(dòng)取消事件的注冊,LiveData不需要。 -
LiveData是通過接口回調(diào)的方式通知訂閱者,EventBus通過反射找到標(biāo)有其注解的方法通知訂閱者。