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