Android消息總線LiveDataBus
Android 的生命周期比較複雜,一般情況下隻能覆寫 Activity / Fragment 的回調方法(onCreate、onResume、onPause、onStop、onDestroy 等)才能監聽生命周期,樣闆代碼少不了,可維護性也較差。
Google 為了幫助 Android 開發者更快更好地開發 App,推出了一系列元件,這些元件被打包成了一個整體,稱作 Android Jetpack,其中部分元件組成了Android Architecture Components,以下簡稱 AAC。
其中LiveData是其中一個元件, LiveData是一個觀察者模型,觀察 Lifecycle 的變化進而影響資料的分發。正是由于LiveData對元件生命周期可感覺特點,是以可以做到僅在元件處于生命周期的激活狀态時才更新UI資料。
LiveData需要一個觀察者對象,一般是Observer類的具體實作。當觀察者的生命周期處于STARTED或RESUMED狀态時,LiveData會通知觀察者資料變化;在觀察者處于其他狀态時,即使LiveData的資料變化了,也不會通知。
LiveDataBus 與其他總線對比
優點
- LiveData具有生命周期感覺的能力,隻有在活躍狀态才會通知資料變化,非常适合作為Android通信總線的基礎構件。
- 與其他總線相比,LiveData使用者不用顯示調用反注冊方法,避免記憶體洩露等其他界面結束後的異常情況。
- LiveDataBus 實作簡單,依賴官方元件LiveData。如果已經使用了AAC或者 Android Jetpack全家桶LiveData幾乎不會增加包大小。
缺點
-
隻存儲最新的資料,LiveData
在UI線程執行,及時更新狀态到活躍頁面,setValue
非UI線程更新狀态,快速調用隻有最新的資料會被送達。雖然LiveData用法類似 RxJava2 的 Flowable,但是它不支援背壓(backpressure),是以不是一個流(stream),利用 LiveDataReactiveStreams 我們可以實作 Flowable 和 LiveData 的互換。postValue
-
是一個觀察者模型,但是它是一個與LiveData
綁定了的Lifecycle
,也就是說,隻有當 UI 元件處于 ACTIVE 狀态時,它的Subject
才能收到消息,否則會自動切斷訂閱關系,不會像Observer
那樣可以通過RxJava
來手動處理。這是個優點,同時在某些場景也會被認為是缺點。CompositeDisposable
- LiveData 的資料天生是sticky的,在LiveData後注冊的observe會收到上次LiveData發送的消息,如果我們要把 LiveData 用作事件總線,還需要做一些定制。
LiveDataBus 的實作
public class LiveDataBus {
private static volatile LiveDataBus instance;
private final ConcurrentHashMap<Object, BusLiveData<Object>> mBus;
private LiveDataBus() {
mBus = new ConcurrentHashMap<>();
}
public static LiveDataBus get() {
if (instance == null) {
synchronized (LiveDataBus.class) {
if (instance == null) {
instance = new LiveDataBus();
}
}
}
return instance;
}
public <T> MutableLiveData<T> subscribe(Object eventKey, Class<T> type) {
String key = eventKey.toString();
if (mBus.containsKey(key) && mBus.get(key) != null) {
BusLiveData busLiveData = mBus.get(key);
busLiveData.firstSubscribe = false;
} else {
mBus.put(key, new BusLiveData<>(key, true));
}
return (MutableLiveData<T>) mBus.get(key);
}
public <T> MutableLiveData<T> setValue(T eventKey, T value) {
Class<T> tClass = (Class<T>) value.getClass();
MutableLiveData<T> mutableLiveData = subscribe(eventKey, tClass);
mutableLiveData.setValue(value);
return mutableLiveData;
}
public <T> MutableLiveData<T> postValue(T eventKey, T value) {
Class<T> tClass = (Class<T>) value.getClass();
MutableLiveData<T> mutableLiveData = subscribe(eventKey, tClass);
mutableLiveData.postValue(value);
return mutableLiveData;
}
public static class BusLiveData<T> extends MutableLiveData<T> {
private boolean firstSubscribe;
private String key;
BusLiveData(String key, boolean firstSubscribe) {
this.key = key;
this.firstSubscribe = firstSubscribe;
}
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
super.observe(owner, new ObserverWrapper<>(observer, firstSubscribe));
}
@Override
public void observeForever(@NonNull Observer<? super T> observer) {
super.observeForever(new ObserverWrapper<>(observer, firstSubscribe));
}
@Override
public void removeObserver(@NonNull Observer<? super T> observer) {
super.removeObserver(observer);
if (!hasObservers()) {
LiveDataBus.get().mBus.remove(key);
}
}
}
private static class ObserverWrapper<T> implements Observer<T> {
private Observer<T> observer;
private boolean isChanged;
private ObserverWrapper(Observer<T> observer, boolean isFirstSubscribe) {
this.observer = observer;
isChanged = isFirstSubscribe;
}
@Override
public void onChanged(@Nullable T t) {
if (isChanged) {
if (observer != null) {
observer.onChanged(t);
}
} else {
isChanged = true;
}
}
}
}
上面提到LiveData的缺點時說過:在LiveData後注冊的observe會收到上次LiveData發送的消息,是以上面代碼定制了firstSubscribe字段避免這種情況發生。
使用方法:
LiveDataBus.get().subscribe("test", Boolean.class).observe(this, new Observer<Boolean>() {
@Override
public void onChanged(@Nullable Boolean aBoolean) {
}
});
ps:如果希望在任何時候都監聽消息可以使用
observeForever
方法,如果隻是希望在更廣闊的生命周期監聽,比如說在create到destroy之間監聽事件,可以參考繼承修改
LifecycleBoundObserver
類的
shouldBeActive
方法,具體實作參考ExternalLiveData