一、概述
EventBus是一款针对Android优化的发布/订阅(publish/subscribe)事件总线。当我们进行项目开发的时候,往往是需要应用程序的各组件、组件与后台线程间进行通信,比如在子线程中进行请求数据,当数据请求完毕后通过Handler或者是广播通知UI,两个Fragment自检可以通过Listener进行通信等。当我们的项目越来越复杂,使用Intent、Handler、BroadcastReceiver进行模块间通信、模块与后台线程进行通信时,代码量大,而且高度耦合。EventBus就可以替代Intent、Handler、BroadcastReceiver在Fragment、Activity、Service、线程之间传递消息。简化了应用程序内各组件间、组件与后台线程间的通信。开销小,代码更优雅,而且发送者和接收者解耦。
二、知识点
(一)三要素
1、 Event事件。它可以是任意类型的对象。
2、 Subscriber事件订阅者。在EventBus3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。
3、 Publisher事件的发布者。我们可以在任意线程里发布事件,一般使用默认的单例EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。
(二)四种线程模型-ThreadMode
EventBus3.0有四种线程模型,分别是:
1、 POSTING (默认) 表示事件处理函数的线程跟发布事件的线程在同一个线程。
2、 MAIN 表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
3、 BACKGROUND 表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
4、 ASYNC 表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。
三、基本使用
(一)引入EventBus
compile 'org.greenrobot:eventbus:3.0.0'
(二)定义事件类
事件类就是传递的事件,一个组件向另一个组件发送的信息可以储存在一个类中,该类就是一个事件,会被 EventBus发送给订阅者。
public class MessageEvent {
private String message;
public MessageEvent(String message){
this.message = message;
}
public String getMessage(){
return message;
}
}
(三)注册事件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
}
(四)解除注册
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
(五)接收事件
//订阅方法,当接收到事件的时候,会调用该方法
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent messageEvent){
Toast.makeText(MainActivity.this, messageEvent.getMessage(), 0).show();
}
(六)发送事件
EventBus.getDefault().post(messageEvent);
四、粘性事件
粘性事件就是在发送事件后再订阅该事件也能收到该事件。普通事件是先注册再绑定。
比如在项目中有这样的需求,在FirstActivity发送事件到SecondActivity中做事件的处理。如果再FirstActivity中是使通过EventBus.getDefault.post(xx)发出事件,在SecondActivity中是接收不到消息的。因为是SecondActivit用于接收消息的EventBus还未完成注册,虽然发布者发送消息了,但订阅者还未产生。所以发送粘性事件应该这样写:
(一)发送粘性事件
EventBus.getDefault().postSticky(messageEvent);
(二)接收粘性事件
@Subscribe(threadMode = ThreadMode.MAIN , sticky = true)
public void onEvent(MessageEvent messageEvent) {
Toast.makeText(MainActivity.this, messageEvent.getMessage(), 0);
}
五、注意
1、 接收事件方法必需是public void类型的,并且只有一个参数表示EventType。
2、 消息的接收是根据参数的类型(具体是参数中的类名)来决定执行哪一个接收事件方法的。即:订阅者的处理方法是根据订阅事件的类型来确定订阅函数的。
3、 每个事件可以有多个订阅者。
4、 同一个onEvent函数不能被注册两次,所以不能在一个类和父类中同时注册。