在我們剛學(xué)Android不久,就會學(xué)到用接口回調(diào)來異步通知事件。寫起來也算順手,但是接口回調(diào)需要不斷地設(shè)置listener,耦合性較大,當(dāng)項(xiàng)目越來越復(fù)雜,接口回調(diào)的傳值會形成一張錯(cuò)綜復(fù)雜的網(wǎng),有這樣使用經(jīng)歷的人就會深有感觸。于是,就可以使用EventBus的事件傳遞方法,在發(fā)送著和接收者完全解耦,傳遞接收范圍廣,接下來就學(xué)習(xí)怎樣使用Eventbus。
事件產(chǎn)生過程

EventBus的三要素
Event:事件,可以是任意類型的對象。
Subscriber:事件訂閱者,在EventBus3.0之前消息處理的方法只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,他們分別代表四種線程模型。而在EventBus3.0之后,事件處理的方法可以隨便取名,但是需要添加一個(gè)注解@Subscribe,并且要指定線程模型(默認(rèn)為POSTING)。
Publisher:事件發(fā)布者,可以在任意線程任意位置發(fā)送事件,直接調(diào)用EventBus的post(Object)方法??梢宰约簩?shí)例化EventBus對象,但一般使用EventBus.getDefault()就好了,根據(jù)post函數(shù)參數(shù)的類型,會自動調(diào)用訂閱相應(yīng)類型事件的函數(shù)。
使用步驟
引入庫
implementation 'org.greenrobot:eventbus:3.0.0'
這里可以看到EventBus.getDefault()內(nèi)部調(diào)用的是懶漢式的單例獲取Eventbus對象方法。
/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
創(chuàng)建發(fā)送的實(shí)體類,根據(jù)發(fā)送者的實(shí)體類和接收者的實(shí)體類相匹配來看是否接收事件。
public class PostMsg {
private int num;
private String title;
public PostMsg(int num, String title) {
this.num = num;
this.title = title;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
在任意需要發(fā)送事件的地方發(fā)送消息,對,發(fā)送就是這么簡單:
EventBus.getDefault().post(new PostMsg(100,"這里是標(biāo)題"));
接收消息的地方需要在onCreate()方法中進(jìn)行注冊
EventBus.getDefault().post(this);
在onDestroy()方法中取消注冊(避免內(nèi)存泄漏)
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
接收消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(PostMsg postMsg){
Toast.makeText(getApplicationContext(),postMsg.getNum() + " " + postMsg.getTitle(),Toast.LENGTH_LONG).show();
}
線程模式
public enum ThreadMode {
POSTING,
MAIN,
BACKGROUND,
ASYNC
}
POSTING:訂閱者方法將在發(fā)布事件所在的線程中被調(diào)用。是默認(rèn)的線程模式,該模式不會切換線程,意味著最少的性能開銷。可能會發(fā)生下主線程。
MAIN:訂閱者方法將在主線程中被調(diào)用。
BACKGROUND:訂閱者方法將在后臺線程中被調(diào)用。如果發(fā)布事件的線程不是主線程,那么訂閱者方法將直接在該線程中被調(diào)用。如果發(fā)布事件的線程是主線程,那么將使用一個(gè)單獨(dú)的后臺線程
ASYNC:訂閱者方法將在一個(gè)單獨(dú)的線程中被調(diào)用,該模式可用來執(zhí)行耗時(shí)操作。
粘性事件
當(dāng)有需求需要發(fā)送消息,所有注冊過的Activity都能收到。但是此時(shí)只有一部分Activity創(chuàng)建了,那么此時(shí)發(fā)出消息,未創(chuàng)建的Activity就接收不到消息。粘性事件就解決了該問題。通過 postSticky 發(fā)送粘性事件,這個(gè)事件不會只被消費(fèi)一次就消失,而是一直存在系統(tǒng)中,直到被 removeStickyEvent 刪除掉。
發(fā)布粘性事件
EventBus.getDefault().postSticky(new PostMsg(100,"這里是標(biāo)題"));
接收粘性事件
@Subscribe(sticky = true)
public void onEventMainThread(PostMsg postMsg){
}
移除指定粘性事件
//移除某種類型粘性事件
EventBus.getDefault().removeStickyEvent(ThreadMode.xxx);
//移除某種對象粘性事件
EventBus.getDefault().removeStickyEvent(object);
//移除所有粘性事件
EventBus.getDefault().removeAllStickyEvents();