Android - EventBus

统计时间 2023.4.30
最后版本更新时间 2021.12.8
version 3.3.1
star 24.3k

1.EventBus 的使用场景
2.EventBus 和 BroadcastReceiver 的区别?
3.EventBus 中使用了那些设计模式?
4.EventBus 的注意事项?
5.EventBus 的实现原理?
6.EventBus 的粘性事件是如何实现的?

EventBus 简介

EventBus 是用于 Android 和 Java 的事件总线。
简化了 Activity, Fragment, Thread, Service等之间的通信。
● 解耦事件发送者和接收者(基于观察者的特性)
● 避免复杂且容易出错的依赖关系和生命周期问题
可以设置订阅者的优先级 和 交付的线程
代码更少,质量更好。

使用场景

1.消息通知

比如在详情页面有个数据被点赞了,同步到 列表页面也需要更新

2.组件之间传递较大数据,Intent 会有1MB的限制

通过 Intent 不能传递大数据,会被 Binder 的大小所限制。这时候可以用 EventBus 代替

3.组件化之间的通信

基础使用

1.添加依赖到 build.gradle

implementation 'org.greenrobot:eventbus:3.3.1'

2.定义事件

class MessageEvent

3.准备订阅者

override fun onStart() {
    super.onStart()
    EventBus.getDefault().register(this)
    Log.d("yhblock", "EventBus register")
}

override fun onStop() {
    super.onStop()
    EventBus.getDefault().unregister(this)
    Log.d("yhblock", "EventBus unregister")
}

@Subscribe
fun onMessageEvent(event: MessageEvent) {
    Log.d("yhblock", "onMessageEvent: " + Thread.currentThread().name)
}

4.发布事件

EventBus.getDefault().post(MessageEvent())

指定订阅者的线程

在订阅者的方法中,有些操作可能必须在主线程进行,这时候可以通过 @Subscribe 中的 threadMode 指定方法的执行线程。

@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(event: MessageEvent) {
    Log.d("yhblock", "onMessageEvent: " + Thread.currentThread().name)
}

ThreadMode.POSTING(默认)
会运行在和发布者同一个线程中,不会进行线程切换,没有切换线程的开销。
适合已知的可以在很短时间内完成而不需要主线程的简单任务
ThreadMode.MAIN
如果发布者不在主线程,则会切换到主线程。如果发布者在主线程,和 ThreadMode.POSTING 一样进行处理。
适合操作一定要在主线程的任务,比如更新主线程的 UI。
ThreadMode.MAIN_ORDERED
订阅者将在Android的主线程中被调用。事件总是排队等待稍后交付给订阅者,因此对post的调用将立即返回。这为事件处理提供了更严格和更一致的顺序(因此命名为MAIN_ORDERED)。例如,如果你以主线程模式在事件处理程序中发布另一个事件,第二个事件处理程序将在第一个事件处理程序之前完成(因为它是同步调用的-将其与方法调用进行比较)。对于MAIN_ORDERED,第一个事件处理程序将完成,然后第二个事件处理程序将在稍后的时间点(只要主线程有容量)被调用。
使用此模式的事件处理程序必须快速返回,以避免阻塞主线程。
ThreadMode.BACKGROUND
如果发布者在主线程,会切换到后台线程处理。如果发布者在后台线程,会直接在当前线程处理任务。
适合在后台线程执行的短时间任务
ThreadMode: ASYNC
会单独开启线程
适合像网络请求等在后台执行的耗时操作任务

粘性事件

有时候事件会在订阅之前就发送了,这时候再订阅就会收不到之前的数据了,为了保证可以接收到数据,可以设置数据为粘性。

1.接收粘性事件
@Subscribe(sticky = true)
fun onMessageStickyEvent(event: MessageStickyEvent){
    Log.d("yhblock", "onMessageStickyEvent: " + Thread.currentThread().name)
}
2.发送粘性事件
EventBus.getDefault().postSticky(MessageStickyEvent())

粘性事件是在 EventBus 在当前类注册的时候发送的

EventBus pre register
onMessageStickyEvent: main
EventBus register

注意事项

1.慎用 EventBus

除非大数据传输,状态更新同步等特色场景,其他情况最好不要使用 EventBus,将这个作为最后的方案。因为EventBus的观察者太过于灵活,对于代码的可维护性造成了不少问题。增加了代码的复杂度,特别是接手其他开发者的项目时,太痛苦了

2.粘性事件需要及时取消
3.避免重复注册和取消注册
//注册
if(!EventBus.getDefault().isRegistered(this)) {
    EventBus.getDefault().register(this)
}
//取消注册
if (EventBus.getDefault().isRegistered(this)) {
    EventBus.getDefault().unregister(this)
}

使用建议

1.通过 Lifecycle 关联 EventBus 的生命周期,减少 Activity 中的代码
class LifecycleEventBus : DefaultLifecycleObserver {

    override fun onStart(owner: LifecycleOwner) {
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(owner)
        }
        super.onStart(owner)
    }

    override fun onStop(owner: LifecycleOwner) {
        super.onStop(owner)
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(owner)
        }
    }
}

class MainActivity : AppCompatActivity() {

    private val lifecycleEventBus = LifecycleEventBus()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        lifecycle.addObserver(lifecycleEventBus)
    }
}
2.使用统一的 Event,减少 Event 类的数量
data class CommonEvent(val eventId: Int)

资料

EventBus Documentation

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值