EventBus学习

EventBus 使用

很早之前就听过 EventBus 这个神器了,因为参与了新项目,维护同事的代码,全部用的是 EventBus,有必要学习一下。Android 原生的广播,实际项目中使用的确实是比较少,除非是一些 ROM 开发。我们是实用主义者,所以就先记录如何使用,然后等会用后再去研究原理。

确保EventBus 已添加到项目依赖。

1. 定义Event

Event 没有特殊要求,就是普通的 Java 对象。例如下面的代码,如果不需要传值,可以只写一个空类。

1
2
3
4
5
6
public class MessageEvent {
public final String message;
public MessageEvent(String message) {
this.message = message;
}
}

2. Subscriber订阅者

Subscriber 实现 Event 处理,实现的方法在事件被发布的时调用。Subscriber 方法使用 @subscribe 注解定义。

1
2
3
4
5
6
7
8
9
10
11
// This method will be called when a MessageEvent is posted (in the UI thread for Toast)
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}

// This method will be called when a SomeOtherEvent is posted
@Subscribe
public void handleSomethingElse(SomeOtherEvent event) {
doSomethingWith(event);
}

PS: 对于 EventBus 3,方法名可以自由选择(没有 EventBus 2 中的命名约定)

2.1 注册EventBus

Subscriber 只有在注册后才可以接收到事件。对于 Android ,在 Activity 和 Fragment 中通常应该根据生命周期注册。对于大多数情况,分别在 onStart 和 onStop 注册和反注册就可以,如下代码,也可以根据情况,在 onCreate,或者 onDestroy 中注册和反注册。

1
2
3
4
5
6
7
8
9
10
11
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}

@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}

3. 发布Event

代码中的任意部分都可以发布事件。所有已注册并且匹配该类型的 Subscriber(订阅者)都会收到该事件.

1
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));

ThreadMode

EventBus不仅可以处理传递信息,还可以处理线程切换问题。事件可以发布到与发布线程不同的线程中。

对于 Android,UI 改变必须发生在 UI(main)线程中。另一方面,网络请求或其他任何耗时的任务不得在主线程上运行。EventBus 可以处理这些问题,并与 UI 线程保持协调。

主要有以下四种线程模式

1
2
3
4
5
ThreadMode:POSTING(默认)
ThreadMode:MAIN
ThreadMode:MAIN_ORDERED
ThreadMode:BACKGROUND
ThreadMode:ASYNC

查看了官方的英文文档,MAIN 与 MAIN_ORDERED 模式,Subscriber 都是运行在主线程的,区别是 MAIN_ORDERED 保证了事件处理有一个更严格一致的顺序。

比如,在 MAIN 模式下,处理事件的时候发布另一个事件,则第二个事件将先于第一个事件被处理完成(此处为同步调用,可与方法调用类比)。而对于 MAIN_ORDERED,第一个事件将先被完成处理,然后第二个事件在稍后的时间点(一旦主线程有处理能力时)被处理。

BACKGROUND 事件回调将在后台线程中被调用。如果发布事件的线程不是主线程,事件回调将直接在发布线程被调用。否则,EventBus 使用一个后台线程(单例)来按序调用每个回调

ASYNC 事件回调方法总是在单独的线程被调用。这些线程不会是发布事件的线程,也不会是主线程。

官方文档
参考文档