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

猜你喜欢

转载自blog.csdn.net/Android_yh/article/details/130451079