EventBus是一种用于Android的发布/订阅事件总线。能够简化各组件之间、组件与后台线程间的通信。可以实现如下需求:请求网络,网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通过Listener通信等。能有效分离事件发送方和接收方(解耦)。
EventBus使用的三步骤
1、定义事件
2、订阅事件
3、发布事件
一、定义事件:任意的java对象,没有特殊要求
public class MessageEvent {
private String message;
public MessageEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
二、订阅事件:
订阅者需要实现事件的处理方法(也称“订阅者方法”),这些方法将在事件发布时调用。EventBus 3使用了@Subscribe注解来定义订阅者方法。方法名可以是任意方法名,参数为订阅事件的类型。
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMoodEvent(MessageEvent messageEvent){
tv_message.setText(messageEvent.getMessage());
}
订阅者还要在总线上注册,但不需要在总线上注销。只要订阅者注册了,他们才可以收到事件。可以根据activity和fragment的生命周期来注册和注销。
@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);
}
三、发布事件。
在需要的地方发布事件,所有订阅了该类型的事件并已经注册的订阅者将收到该事件。
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
线程
事件可以发布在与发布线程不同的线程中,比如UI更新必须在主线程中完成,网络请求一般在子线程中处理,网络请求结束后,可以直接发布UI更新操作,而不需要使用Handler、AsyncTask等。共支持如下5种线程模式:
1、ThreadMode.POSTING 订阅者方法将在发布事件所在的线程中被调用。这是默认的线程模式。事件的传递是同步的,一旦发布事件,所有该模式的订阅者方法都将被调用。这种线程模式意味着最少的性能开销,因为它避免了线程的切换。因此,对于不要求是主线程并且耗时很短的简单任务推荐使用该模式。使用该模式的订阅者方法应该快速返回,以避免阻塞发布事件的主线程。
2、ThreadMode.MAIN 订阅者方法将在主线程(UI线程)中被调用。因此,可以在该模式的订阅者方法中直接更新UI界面。如果发布事件的线程是主线程,那么该模式的订阅者方法将被直接调用。使用该模式的订阅者方法必须快速返回,以避免阻塞主线程。
3、ThreadMode.MAIN_ORDERED 订阅者方法将在主线程(UI线程)中被调用。因此,可以在该模式的订阅者方法中直接更新UI界面。事件将先进入队列然后才发送给订阅者,所以发布事件的调用将立即返回。这使得事件的处理保持严格的串行顺序。使用该模式的订阅者方法必须快速返回,以避免阻塞主线程。
4、ThreadMode.BACKGROUND 订阅者方法将在后台线程中被调用。如果发布事件的线程不是主线程,那么订阅者方法将直接在该线程中被调用。如果发布事件的线程是主线程,那么将使用一个单独的后台线程,该线程将按顺序发送所有的事件。使用该模式的订阅者方法应该快速返回,以避免阻塞后台线程。
5、ThreadMode.ASYNC 订阅者方法将在一个单独的线程中被调用。因此,发布事件的调用将立即返回。如果订阅者方法的执行需要一些时间,例如网络访问,那么就应该使用该模式。避免触发大量的长时间运行的订阅者方法,以限制并发线程的数量。EventBus使用了一个线程池来有效地重用已经完成调用订阅者方法的线程。
粘性事件
粘性事件:就是在发送事件之后再订阅该事件也能收到该事件。EventBus将在内存中缓存该粘性事件。当有订阅者订阅后,也能获取到该事件。
//订阅粘性事件
@Subscribe(sticky = true)
public void ononMoonStickyEvent(MessageEvent messageEvent){
tv_message.setText(messageEvent.getMessage());
}
//发布粘性事件
EventBus.getDefault().postSticky(new MessageEvent("粘性事件"));
移除粘性事件:
// 移除指定的粘性事件
removeStickyEvent(Object event);
// 移除指定类型的粘性事件
removeStickyEvent(Class<T> eventType);
// 移除所有的粘性事件
removeAllStickyEvents();
优先级
EventBus支持在定义订阅者方法时指定事件传递的优先级。默认情况下,订阅者方法的事件传递优先级为0。数值越大,优先级越高。在相同的线程模式下,更高优先级的订阅者方法将优先接收到事件。注意:优先级只有在相同的线程模式下才有效。
@Subscribe(priority = 1)
public void onMoodEvent(MessageEvent messageEvent){
tv_message.setText(messageEvent.getMessage());
}