為什么要用EventBus:
EventBus是一個事件總線框架,觀察者模式的變形,利用這個框架,我們可以方便高效地在Android組件間傳遞和處理數據,切換線程,降低代碼耦合度。
本文基于 EventBus 3.0。
簡單使用
- 配置build.gradle
dependencies {
implementation 'org.greenrobot:eventbus:3.0.0'
}
?
- 觀察者Java代碼(以Activity為例)
@Override
protected void onResume() {
super.onResume();
EventBus.getDefault().register(this); //訂閱事件
}
@Override
protected void onPause() {
super.onPause();
EventBus.getDefault().unregister(this); //Activity進入后臺,取消訂閱事件
}
/**
* 事件開始傳遞時會回調包含 @Subscribe 這個注釋的方法
* @param event 傳遞的數據(Object,為了方便這里直接用String)
*/
@Subscribe
public void onEvent(String event) {
}
?
- 發送事件
EventBus.getDefault().post("This is an event transfered by EventBus");
發送事件后,所有訂閱事件的觀察者會回調包含 @Subscribe
這個注釋且方法參數為String
的方法,可以把String
換成任何我們需要的Object
來傳遞數據。
下面說一下EventBus的進階使用。
線程模式
EventBus總共有四種線程模式:
ThreadMode.POSTING
這是缺省模式,onEvent
會在發布事件的線程中運行,即發布事件和接收處理事件將會運行在同一個線程。
這種模式下不要在onEvent
中執行耗時操作,否則會延遲其他觀察者的對事件的接收,阻塞線程。ThreadMode.MAIN
不論事件是在哪個線程中發布出來的,onEvent
都會在UI線程中執行,即接收處理事件運行在UI線程中。
當分發事件的線程不在UI線程中時,可以使用這種方法來更新UI。
這種模式下不要在onEvent
中執行耗時操作,否則會延遲其他觀察者的對事件的接收,阻塞線程。ThreadMode.BACKGROUND
如果事件從UI線程中分發,那么onEvent
就會在子線程中運行,如果事件本來就是子線程中發布出來的,那么onEvent
函數直接在該子線程中執行。
這種模式下不要在onEvent
中執行耗時操作,否則會延遲其他觀察者的對事件的接收,阻塞線程。ThreadMode.ASYNC
無論事件在哪個線程發布,都會創建新的子線程來執行onEvent
。用例
@Subscribe (threadMode = ThreadMode.ASYNC)
public void onEvent(String event) {
}
粘性事件和事件優先級
這兩個概念類似于粘性廣播和有序廣播,就不具體解釋了,看一下用法
- 粘性事件
@Subscribe (sticky = true) //聲明可接收粘性事件
public void onEvent(Message m) {
}
EventBus.getDefault().postSticky("Post a sticky event");
這樣即便事件先發出去,觀察者后訂閱的事件,也可以回調onEvent
?
- 事件優先級
@Subscribe (priority = 2) //聲明接收事件的優先級,默認為0,優先級最小
public void onEvent(Message m) {
//類似于有序廣播,也可以阻止事件繼續分發
EventBus.getDefault().cancelEventDelivery(event) ;
}
事件發送后,會按照優先級的順序來接收事件。
注解處理器
上文中對EventBus的使用是最基本的使用方法,因為觀察者類信息要通過反射獲取,所以效率有所欠缺,這里推薦使用Google的注解處理器AnnotationProcessor
,在編譯期獲取類信息,生成索引,提高運行效率。下面說一下如何配置:
- 配置build.gradle
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [ eventBusIndex : 'org.greenrobot.eventbusperf.EventBusIndex' ]
}
}
}
dependencies {
...
implementation 'org.greenrobot:eventbus:3.0.0'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
- 應用初始化時配置
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
EventBus.builder().addIndex(new EventBusIndex()).installDefaultEventBus();
}
}
這樣配置之后,EventBus的效率就得到了提高,具體使用方法和之前相同。
使用EventBus后的代碼混淆
使用EventBus后,代碼混淆配置如下:
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}