EventBus替换方案--EventLiveData和事件池
EventBus的缺点
EventBus作为一个常用的的事件总线库,它的确很优秀,将消息的传输过程简易化了
然而它有着几个致命的缺点:
- 需要注册和解除注册,过程繁琐
- 当事件很多的时候追查事件流异常困难
- 每个对象只能对应一个事件,所以不同事件基本都需要一个事件对象存在
其中第二点是最让人不能忍的,
针对第二点举例,比如我们需要post一个名为DownloadInfo的一个对象
EventBus.getDefault().post(downloadInfo);
如果我们需要追查这个对象被发送到了哪里,那只能根据这个对象来查找
然后就会发现如下情况
哎,一堆引用,想查对象发送的地方真是够呛.
尤其是看别人代码的时候,简直是生无可恋啊
EventLiveData
针对EventBus以上痛点,我是不太想用它了,于是EventLiveData顺势而生.
这是基于LiveData魔改的一个类,用于实现事件发送.
EventLiveData可以在后台线程发送事件,不过接收事件的线程是主线程并且不能切换.
EventLiveData构造方法有两个参数:
- stickyCount: Int 表示粘性事件发送次数和发送模式
- activeForever: Boolean 是否一直处于激活状态
stickyCount
stickyCount如果大于0则表示粘性事件发送次数,也就是说通过EventLiveData发送事件之后注册的观察者也能收到事件,不过有次数限制,当次数消耗完,再之后的注册的观察者便不会收到事件了;
stickyCount如果等于EventLiveData.NO_STICKY则表示非粘性事件,只有已经注册的观察者才能收到;
stickyCount如果等于EventLiveData.STICKY_FOREVER则表示为永久的粘性事件,已注册的观察者和将来注册的观察者都会收到事件;
stickyCount如果等于EventLiveData.SEND_ONCE则表示此事件只会发送一次.如果已经有观察者,则事件会发送给所有现在已注册的观察者,之后注册的观察者不会收到事件,如果暂时没有观察者,那么事件只会发送给将来第一个注册的观察者.
activeForever
常规的LiveData有个特点,就是在界面不可见的时候是收不到消息的,然而如果拿来做个事件发送,这样可能并不合适,有时候我们需要在页面不可见的时候也能收到事件.
activeForever如果为true则表示不管任何时候都会收到事件,如果为false则表示仅在页面可见的时候才会收到消息.
当然这个属性对于observeForever是无效的,observeForever无法感知生命周期变化,所以不管任何时候都会收到事件.
EventLiveData的使用
EventLiveData依赖
allprojects {
repositories {
//...
maven { url 'https://www.jitpack.io' }
}
}
dependencies {
implementation 'com.github.dqh147258:EventLiveData:1.0.+'
}
除了上述的两个构造参数,其它使用和普通的LiveData并没有什么区别.
举例说我们有一个用户信息需要更新的事件,我们创建如下对象即可
val userInfoShouldUpdateEvent = EventLiveData(SEND_ONCE, false)
然后在合适的地方注册观察者
userInfoShouldUpdateEvent.observe(owner) {
getUserInfo()
}
当我们需要发送事件的时候只需要调用
userInfoShouldUpdateEvent.value = true
或者
userInfoShouldUpdateEvent.postValue(true)
事件池
我们需要一个单例类用于存放EventLiveData,我将其称之为事件池,只是为了方便管理和方便访问,其并无其它功能.
我们可以将所有或者大部分EventLiveData都放在名为EventPool(事件池)的单例类中
object EventPool {
/**
* 用户信息更新事件
*/
val userInfoUpdateEvent = EventLiveData(STICKY_FOREVER, false)
/**
* 用户信息需要更新事件
*/
val userInfoShouldUpdateEvent = EventLiveData(SEND_ONCE, false)
//......
}
然后在合适的地方注册和使用
EventPool.userInfoShouldUpdateEvent.observe(owner) {
getUserInfo()
}
EventPool.userInfoShouldUpdateEvent.value = true
如果我们需要增加一个事件则只需要在EventPool中增加一个EventLiveData.
结语
综上,通过EventLiveData和事件池,我们便没有了类似EventBus的3个缺点.
通常来说对于Activity和Fragment我们并不需要解除观察者的注册,所以使用起来并不繁琐;
我们也并不需要根据事件对象来追查事件流,根据EventLiveData本身的引用追查即可,这样追查也变得方便快捷;
不同的事件只需要创建不同名的EventLiveData对象即可,我们不需要对不同事件创建不同的事件对象.
GitHub地址
https://github.com/dqh147258/EventLiveData