EventBus简介
- 相关网页:GitHub地址、官方文档。
- EventBus 是一个 publish/subscribe 事件总线,简化了应用程序各个组件间( Activity , Service , Fragment 等),组件和 后台线程 间的通信。
- 比如 网络请求 完毕后返回时,通过
Handler
或者 Broadcast 通知 UI 以及Fragment
之间的通信等功能都可以通过 EventBus 实现。
简单示例
1. 定义事件类
// 事件类的结构无关紧要
public class EventBusMsg {
public String name;
public EventBusMsg(String name) {
this.name = name;
}
}
2. 订阅与取消订阅事件
1. 订阅事件
在Activity
或Fragment
的onCreate(...)
或onResume()
等方法内登记,注意生命周期对齐。
EventBus.getDefault().register(MainActivity.this);
2. 取消订阅事件
在Activity
或Fragment
的onDestory()
或onPause()
等方法内取消登记,注意生命周期对齐。
EventBus.getDefault().unregister(MainActivity.this);
3. 定义事件处理方法
在 订阅者 (Activity
、Fragment
等)内定义 事件处理方法 :
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventBusMsgEvent(EventBusMsg event) {
Log.d(TAG, "接收到信息");
}
- 使用
@Subscribe()
注解来表明这个方法是 EventBus 事件接收的方法。 - 事件接收方法的参数必须和
EventBus
发送的事件类是同一类型,比如此处使用了EventBusMsg
类. - 在
@Subscribe()
中可以设置threadMode
来设置不同的模式。关于threadMode
下面会有讲解,这里使用ThreadMode.MAIN
表明这个方法运行在 UI主线程 中。
4. 发布事件
EventBus.getDefault().post(new EventBusMsg("我是EventBus发送的数据"));
ThreadMode
的四种线程模式
1. POSTING
-
POSTING
是默认模式。 - 保证事件发布和 事件处理方法 在同一个 线程 中。
- 这种模式下开销最小,因为不需要切换 线程 。
@Subscribe(threadMode = ThreadMode.POSTING)
public void onXEvent(EventBusMsg event) {
Log.d(TAG, "接收到信息");
}
2. MAIN
- 保证 事件处理方法 运行在 UI主线程 中。
- 如果发布事件的 线程 是 主线程 那么事件就会直接发布给 订阅者 ,不会进行线程切换,否则,切换 线程 后发布。
- 警告: 事件处理方法 应当尽快返回,避免阻塞 UI主线程 。
@Subscribe(threadMode = ThreadMode.MAIN)
public void onXEvent(EventBusMsg event) {
Log.d(TAG, "接收到信息");
}
3. BACKGROUND
- 保证 事件处理方法 将会运行在一个 后台线程 中。
- 如果事件发布本身就在 后台线程 中,那么 事件处理方法 就运行在这个 线程 中,不在另外开启新的 线程 。
- 如果发布事件在 UI主线程 中,那么 EventBus 会开一个 后台线程 然后在该 线程 中依次处理所有事件。
- 警告: 事件处理方法 应当尽快返回,避免阻塞事件发布的 后台线程 。
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onXEvent(EventBusMsg event) {
Log.d(TAG, "接收到信息");
}
4. ASYNC
- 保证 事件处理方法 总是运行在一个 发布事件的线程 和 UI主线程 之外 独立的线程 中。
- 发布事件不必依赖 订阅者 事件处理的结果,也不会阻塞 发布事件的线程 或 UI主线程 。
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onXEvent(EventBusMsg event) {
Log.d(TAG, "接收到信息");
}
粘性事件
简介
- 粘性事件 允许先发布事件再订阅事件。
- EventBus 会将 粘性事件 保存在内存中然后发送给 订阅者 , 订阅者 也可以主动查询 粘性事件 。
- 应用场景 :如果 App 中有定位或传感器数据等需要重复获取的数据,可以使用 粘性事件 而不是每次都去发布事件通知 订阅者 这些数据变更了。
简单示例
1. 定义事件
// 事件类的结构无关紧要
public class EventBusMsg {
public String name;
public EventBusMsg(String name) {
this.name = name;
}
}
2. 发布粘性事件
// 先发布事件
EventBus.getDefault().postSticky(new EventBusMsg("我是Sticky消息"));
// 后启动事件订阅方Activity
Intent intent = new Intent(MainActivity.this, EventBusSendActivity.class);
MainActivity.this.startActivity(intent);
3. 粘性事件的两种使用方式
订阅
1. 订阅与取消订阅事件
参考上文。
2. 定义事件处理方法
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventBusMsgEvent(EventBusMsg event) {
Log.d(TAG, "接收到信息");
}
手动获取
获取
EventBusMsg msg = EventBus.getDefault().getStickyEvent(EventBusMsg.class);
移除
EventBus.getDefault().removeStickyEvent(EventBusMsg.class);
EventBus.getDefault().removeAllStickyEvents();
事件处理方法优先级
设置优先级
-
事件处理方法 默认优先级为
0
,值越大,优先级越高,值越小,优先级越低。 - 对于同一个 线程 下的所有 事件处理方法 ,优先级越高,越先调用。
- 优先级对于来自不同线程的 事件处理方法 没有影响。
@Subscribe(priority = 1);
public void onEvent(MessageEvent event) {
// ...
}
取消事件传递
- 优先级高的 事件处理方法 可以通过 取消事件传递 来使得优先级低的 事件处理方法 无法接收到事件。
- 取消事件传递 局限于 事件处理方法 所在的 线程 。
EventBus.getDefault().cancelEventDelivery(event);