本文主要翻譯自:
https://github.com/greenrobot/EventBus/blob/master/HOWTO.md
1. 功能介紹
1.1. EventBus
EventBus 是一個 Android 事件發(fā)布/訂閱框架,通過解耦發(fā)布者和訂閱者簡化 Android 事件傳遞。
1.2 主要對象
事件 (Event)
發(fā)布者 (Publisher)
訂閱者 (Subscriber)
2. 流程圖
3. 類圖
4. 使用方法
4.1 使用EventBus三步
定義事件:
public class MessageEvent {
public final String message;
public MessageEvent(String message) {
this.message = message;
}
}
訂閱者注冊事件
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
// This method will be called when a MessageEvent is posted
public void onEvent(MessageEvent event){
Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
// This method will be called when a SomeOtherEvent is posted
public void onEvent(SomeOtherEvent event){
doSomethingWith(event);
}
發(fā)布事件
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
4.2 交付線程和ThreadModes
事件可以在不同的線程之間傳遞
ThreadMode:
-
PostThread
這是默認的模式,訂閱者會在發(fā)布者所在的線程中調(diào)用。這種模式開銷最小,避免了線程之間的切換。所以完成時間很短,并且不需要主線程參與的簡單任務(wù)建議使用這種模式。例如:
// Called in the same thread (default)
public void onEvent(MessageEvent event) {
log(event.message);
}
-
MainThread
這種模式訂閱者會在主線程中調(diào)用。如果事件發(fā)布是在主線程,那么事件處理程序會立即被調(diào)用。使用這種模式事件處理必須盡快返回,以避免阻塞主線程。例如:
// Called in Android UI's main thread
public void onEventMainThread(MessageEvent event) {
textField.setText(event.message);
}
-
BackgroundThread
這種模式訂閱者會在后臺線程中調(diào)用。如果事件發(fā)布不在主線程,事件處理方法會直接在發(fā)布線程中調(diào)用;如果事件發(fā)布在主線程,EventBus則會依次傳遞所有的事件到一個后臺進程。使用這種模式必須盡快返回以避免阻塞后臺進程。
// Called in the background thread
public void onEventBackgroundThread(MessageEvent event){
saveToDisk(event.message);
}
-
Async
事件處理方法在一個單獨的線程中調(diào)用。他始終是獨立于發(fā)布線程和主線程。發(fā)布事件不需要等待事件處理方法的完成。如果使用耗時的操作應(yīng)當使用這種模式,比如連接網(wǎng)絡(luò)。應(yīng)當避免同一時間觸發(fā)大量的、長時間運行的異步處理方法,從而限制并發(fā)線程的數(shù)量。EventBus使用了線程池來有效的重用線程。
// Called in a separate thread
public void onEventAsync(MessageEvent event){
backend.send(event.message);
}
4.3 訂閱者優(yōu)先級以及事件傳遞順序
我們可以通過定義優(yōu)先級來決定事件的傳遞順序
int priority = 1;
EventBus.getDefault().register(this, priority);
在同一個ThreadMode中,優(yōu)先級高的訂閱者會先接收到事件。默認的優(yōu)先級是0。優(yōu)先級在不同的ThreadModes中是沒有效果的
4.4 使用EventBusBuilder配置EventBus
EventBus2.3增加了EventBusBuilder來配置EventBus。例如:配置一個當事件沒有訂閱者的時候,發(fā)布一個事件時,EventBus不做任何事情。
EventBus eventBus = EventBus.builder()
.logNoSubscriberMessages(false)
.sendNoSubscriberEvent(false).build();
更多設(shè)置請查看 EventBusBuilder 類和他的javaDoc
4.5 配置默認的EventBus實例
最簡單的方式是使用EventBus.getDefault()來獲取一個共享的EventBus實例,同時可以使用EventBusBuilder的installDefaultEventBus()來創(chuàng)建默認實例。
例如:可能需要配置一個默認的EventBus實例來將在onEvent()方法中的例外再次拋出,但是我們只想在debug模式中這樣做,因為這位導(dǎo)致app的崩潰。
EventBus.builder().throwSubscriberException(BuildConfig.DEBUG).installDefaultEventBus();
在EventBus實例第一次使用前,這種配置只能做一次,從而確保在應(yīng)用程序中的一致性。最好的地方是在Application類中進行初始化。
4.6 取消事件發(fā)送
當取消事件發(fā)送后,后面的訂閱者就不再會接收到事件
// Called in the same thread (default)
public void onEvent(MessageEvent event){
// Process the event
...
EventBus.getDefault().cancelEventDelivery(event) ;
}
事件通常是在較高優(yōu)先級的訂閱者中取消。取消動作僅限于運行在發(fā)布線程的事件處理方法。
4.7 sticky事件
一些事件攜帶的信息只有在其發(fā)布之后才會被關(guān)注。例如,有些事件會標記一些初始化的完成。或者一些傳感器或者位置數(shù)據(jù)需要獲取最新的值,這些情況我們就可以使用sticky事件。EventBus會在內(nèi)存中保留某種類型最新的sticky事件
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
在stickyEvent發(fā)布后,當有新的Activity啟動,并注冊了sticky事件,他就會立刻收到該事件
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().registerSticky(this);
}
public void onEventMainThread(MessageEvent event) {
textField.setText(event.message);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
我們也可以來獲取指定類型的sticky事件
EventBus.getDefault().getStickyEvent(Class<?> eventType)
4.8 混淆的配置
-keepclassmembers class ** {
public void onEvent*(**);
}
# Only required if you use AsyncExecutor
-keepclassmembers class * extends de.greenrobot.event.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
5. 加入EventBus到項目中
Gradle:
compile 'de.greenrobot:eventbus:2.4.0'
Maven:
<dependency>
<groupId>de.greenrobot</groupId>
<artifactId>eventbus</artifactId>
<version>2.4.0</version>
</dependency>