简介

Eventbus是适用于Android和Java的发布/订阅事件总线,简化了应用程序内各组件、组件与后台线程之间的通信。

角色

  • Event:事件,可以是任意类型,EventBus会根据事件类型进行全局通知。
  • Subscriber:事件订阅者,事件处理的方法名随意,不过需要注解@subscribe和指定线程模式(默认POSTING)。
  • Publisher:事件发布者,可以在任意线程中发布事件,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。

线程模式

  • POSTING:默认,表示事件处理函数线程与发布事件线程在同一线程中。可以避免线程切换因此速度最快。注意应尽快返回避免阻塞可能在主线程中的发布线程。
  • MAIN:表示事件处理函数线程在主线程(UI线程)中。注意应尽快返回避免阻塞主线程。
  • MAIN_ORDERED:表示事件处理函数线程在Android主线程中。事件将始终排入队列,拥有更严格和更一致的顺序。注意应尽快返回避免阻塞。
  • BACKGROUND:表示事件处理函数线程在后台线程中。如果发布事件线程在主线程(UI线程)中,则事件处理函数将会开启一个后台线程;如果发布事件线程是在后台线程,那么事件处理函数就使用该后台线程。注意应尽快返回避免阻塞主线程。
  • ASYNC:表示事件处理函数将会在新建子线程中。如果执行可能需要一些时间,则应使用此模式。

关系图

图片

优点

EventBus可以是替代IntentHandlerBroadCastActivityFragmentService线程之间传递消息。拥有速度快、消耗低、代码优雅、高级功能、将事件发布者与事件订阅者解耦等优点。

教程

导入

build.gradle(Module)中添加EventBus依赖。

build.gradle(Module)
1
2
3
4
dependencies {
...
implementation 'org.greenrobot:eventbus:3.2.0'
}

定义事件

此事件由Publisher(事件发布者)发出,到Subscriber(事件订阅者)接收。

MessageEventBus.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import android.os.Bundle;

public class MessageEventBus {

private String type;
private Bundle data;

public MessageEventBus(String type, Bundle data) {
this.type = type;
this.data = data;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public Bundle getData() {
return data;
}

public void setData(Bundle data) {
this.data = data;
}

}

注册与注销事件订阅者

通常根据ActivityFragmentService的生命周期进行注册。

MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//EventBus-Register
EventBus.getDefault().register(this);
}

@Override
protected void onDestroy() {
super.onDestroy();
//EventBus-Unregister
EventBus.getDefault().unregister(this);
}

定义事件订阅者

MainActivity.java
1
2
3
4
5
6
7
8
9
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventBus(MessageEventBus message) {
Bundle data = message.getData();
switch (message.getType()) {
case "simple":
data.getString("value")
break;
}
}

发布事件

MainActivity.java
1
2
3
Bundle data = new Bundle();
data.putString("value", "test");
EventBus.getDefault().post(new MessageEventBus("simple", data));

粘性事件

EventBus将某种类型的最后一个粘性事件保留在内存中,然后粘性事件就可以被事件订阅者收到或被查询。

示例

某个粘性事件在一段时间前发布。

MainActivity.java
1
EventBus.getDefault().postSticky(new MessageEventBus("sticky", null));

然后定义一个粘性事件订阅者,它将立即收到之前发布过的粘性事件。

MainActivity.java
1
2
3
4
@Subscribe(sticky = true)
public void onEventBus(MessageEventBus message) {
···
}

删除

当不需要使用某个粘性事件时,可以将其删除,并且会返回之前的粘滞事件。

MainActivity.java
1
MessageEventBus event = EventBus.getDefault().removeStickyEvent(MessageEventBus.class);

优先级

可以通过提供优先级以改变事件传递的顺序。在同一ThreadMode(传递线程)中,优先级较高的订阅者将在优先级较低的订阅者之前收到事件,默认优先级为0。

MainActivity.java
1
2
3
4
@Subscribe(priority = 1)
public void onEventBus(MessageEventBus message) {
···
}

取消事件传递

如果不需要事件继续传递,可以取消事件传递,仅限于在POSTING线程模式中。

MainActivity.java
1
2
3
4
5
@Subscribe(threadMode = ThreadMode.POSTING)
public void onEventBus(MessageEventBus message) {
···
EventBus.getDefault().cancelEventDelivery(message);
}

混淆规则

如果项目使用了ProGuard,则需要在proguard-rules.pro中添加指定规则。

proguard-rules.pro
1
2
3
4
5
6
7
8
9
10
-keepattributes *Annotation*
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# And if you use AsyncExecutor:
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}

参考资料