EventBus 使用详解
传统的通信方式包括:Handler、BroadcastReceiver、Interface回调等,而 EventBus 简化了应用程序内各组件间、组件与后台线程间的通信。
首先导入依赖
// Android project
implementation("org.greenrobot:eventbus:3.3.1")
// Java project
implementation("org.greenrobot:eventbus-java:3.3.1")
基本使用
使用如同发布订阅,先创建事件,也就是创建任意一个类,这个就是 Event 事件,再使用如下方法发布出去,此时订阅该事件的方法则会被调用
EventBus.getDefault().post(TestEvent())
订阅事件时,需要事先注册EventBus,一般在onStart方法中注册
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().register(this)
}
别忘了还要在onStop方法取消注册
EventBus.getDefault().unregister(this)
订阅事件,也就是写一个方法,参数是事先创好的类(即事件),然后用@Subscribe注解声明,当发布该事件时则调用这个方法,需要携带的数据也可以通过该类携带
@Subscribe(threadMode = ThreadMode.MAIN)
fun onTestEvent(event: TestEvent) {
// 业务
}
四种线程模型
EventBus3.0有四种线程模型,分别是:
- POSTING (默认) 表示事件处理函数的线程跟发布事件的线程在同一个线程。
- MAIN 表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
- BACKGROUND 表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
- ASYNC 表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。
粘性事件
事件通过post发送给EventBus后,当前已经订阅过的方法当然可以收到,但是如果发送的时候还未订阅,后续再订阅也收不到这个事件。例如,一个Activity要求它管理的所有Fragment都能执行某一个事件,但是当前我只初始化了3个Fragment,如果这时候通过post发送了事件,那么当前的3个Fragment当然能收到。但是这个时候又初始化了2个Fragment,那么我必须重新发送事件,这两个Fragment才能执行到订阅方法。
粘性事件就是为了解决这个问题,通过 postSticky 发送粘性事件,这个事件不会只被消费一次就消失,而是一直存在系统中,直到被 removeStickyEvent 删除掉,那么只要订阅了该粘性事件即可收到并执行。
# 发送粘性事件
EventBus.getDefault().postSticky(TestEvent())
# 移除粘性事件
EventBus.getDefault().removeStickyEvent(TestEvent())
接收粘性事件除了用@Subscribe注解声明,还需要添加 sticky = true 属性
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onTestEvent(event: TestEvent) {
// 业务
}
注意事项
- Event 事件。它可以是任意类型。
- Subscriber 事件订阅者。在EventBus3.0之前我们必须定义以onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync开头的方法,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。
- Publisher 事件的发布者。可以在任意线程里发布事件。
使用场景
-
Event会根据传递的参数给所有接收者都传递消息,这就导致如果想给指定一个类里发布消息就得单独写一个事件,要不然就会好多执行者都会执行该方法,所以一般能用Intent组件传值时还是用Intent。
-
activity和fragment交互或fragment之间进行通信,用广播和接口都比较麻烦。
-
交互流程跨多个界面,如发朋友圈,可以拍照或从相册选取照片,可能还需要剪切,但最终也只是需要照片地址,用EventBus传递数据则比较方便
总结:主要是在常规通信方式写起来很复杂或需要解耦的情况下使用EventBus