EventBus替換方案--EventLiveData和事件池
EventBus的缺點
EventBus作為一個常用的的事件總線庫,它的確很優(yōu)秀,將消息的傳輸過程簡易化了
然而它有著幾個致命的缺點:
- 需要注冊和解除注冊,過程繁瑣
- 當(dāng)事件很多的時候追查事件流異常困難
- 每個對象只能對應(yīng)一個事件,所以不同事件基本都需要一個事件對象存在
其中第二點是最讓人不能忍的,
針對第二點舉例,比如我們需要post一個名為DownloadInfo的一個對象
EventBus.getDefault().post(downloadInfo);
如果我們需要追查這個對象被發(fā)送到了哪里,那只能根據(jù)這個對象來查找
然后就會發(fā)現(xiàn)如下情況

哎,一堆引用,想查對象發(fā)送的地方真是夠嗆.
尤其是看別人代碼的時候,簡直是生無可戀啊
EventLiveData
針對EventBus以上痛點,我是不太想用它了,于是EventLiveData順勢而生.
這是基于LiveData魔改的一個類,用于實現(xiàn)事件發(fā)送.
EventLiveData可以在后臺線程發(fā)送事件,不過接收事件的線程是主線程并且不能切換.
EventLiveData構(gòu)造方法有兩個參數(shù):
- stickyCount: Int 表示粘性事件發(fā)送次數(shù)和發(fā)送模式
- activeForever: Boolean 是否一直處于激活狀態(tài)
stickyCount
stickyCount如果大于0則表示粘性事件發(fā)送次數(shù),也就是說通過EventLiveData發(fā)送事件之后注冊的觀察者也能收到事件,不過有次數(shù)限制,當(dāng)次數(shù)消耗完,再之后的注冊的觀察者便不會收到事件了;
stickyCount如果等于EventLiveData.NO_STICKY則表示非粘性事件,只有已經(jīng)注冊的觀察者才能收到;
stickyCount如果等于EventLiveData.STICKY_FOREVER則表示為永久的粘性事件,已注冊的觀察者和將來注冊的觀察者都會收到事件;
stickyCount如果等于EventLiveData.SEND_ONCE則表示此事件只會發(fā)送一次.如果已經(jīng)有觀察者,則事件會發(fā)送給所有現(xiàn)在已注冊的觀察者,之后注冊的觀察者不會收到事件,如果暫時沒有觀察者,那么事件只會發(fā)送給將來第一個注冊的觀察者.
activeForever
常規(guī)的LiveData有個特點,就是在界面不可見的時候是收不到消息的,然而如果拿來做個事件發(fā)送,這樣可能并不合適,有時候我們需要在頁面不可見的時候也能收到事件.
activeForever如果為true則表示不管任何時候都會收到事件,如果為false則表示僅在頁面可見的時候才會收到消息.
當(dāng)然這個屬性對于observeForever是無效的,observeForever無法感知生命周期變化,所以不管任何時候都會收到事件.
EventLiveData的使用
EventLiveData依賴
allprojects {
repositories {
//...
maven { url 'https://www.jitpack.io' }
}
}
dependencies {
implementation 'com.github.dqh147258:EventLiveData:1.0.+'
}
除了上述的兩個構(gòu)造參數(shù),其它使用和普通的LiveData并沒有什么區(qū)別.
舉例說我們有一個用戶信息需要更新的事件,我們創(chuàng)建如下對象即可
val userInfoShouldUpdateEvent = EventLiveData<Boolean>(SEND_ONCE, false)
然后在合適的地方注冊觀察者
userInfoShouldUpdateEvent.observe(owner) {
getUserInfo()
}
當(dāng)我們需要發(fā)送事件的時候只需要調(diào)用
userInfoShouldUpdateEvent.value = true
或者
userInfoShouldUpdateEvent.postValue(true)
事件池
我們需要一個單例類用于存放EventLiveData,我將其稱之為事件池,只是為了方便管理和方便訪問,其并無其它功能.
我們可以將所有或者大部分EventLiveData都放在名為EventPool(事件池)的單例類中
object EventPool {
/**
* 用戶信息更新事件
*/
val userInfoUpdateEvent = EventLiveData<Boolean>(STICKY_FOREVER, false)
/**
* 用戶信息需要更新事件
*/
val userInfoShouldUpdateEvent = EventLiveData<Boolean>(SEND_ONCE, false)
//......
}
然后在合適的地方注冊和使用
EventPool.userInfoShouldUpdateEvent.observe(owner) {
getUserInfo()
}
EventPool.userInfoShouldUpdateEvent.value = true
如果我們需要增加一個事件則只需要在EventPool中增加一個EventLiveData.
結(jié)語
綜上,通過EventLiveData和事件池,我們便沒有了類似EventBus的3個缺點.
通常來說對于Activity和Fragment我們并不需要解除觀察者的注冊,所以使用起來并不繁瑣;
我們也并不需要根據(jù)事件對象來追查事件流,根據(jù)EventLiveData本身的引用追查即可,這樣追查也變得方便快捷;
不同的事件只需要創(chuàng)建不同名的EventLiveData對象即可,我們不需要對不同事件創(chuàng)建不同的事件對象.