天天看點

Android消息總線LiveDataBusAndroid消息總線LiveDataBus

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

    隻存儲最新的資料,

    setValue

    在UI線程執行,及時更新狀态到活躍頁面,

    postValue

    非UI線程更新狀态,快速調用隻有最新的資料會被送達。雖然LiveData用法類似 RxJava2 的 Flowable,但是它不支援背壓(backpressure),是以不是一個流(stream),利用 LiveDataReactiveStreams 我們可以實作 Flowable 和 LiveData 的互換。
  • LiveData

    是一個觀察者模型,但是它是一個與

    Lifecycle

    綁定了的

    Subject

    ,也就是說,隻有當 UI 元件處于 ACTIVE 狀态時,它的

    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