簡(jiǎn)介
EventBus 是一款訂閱——發(fā)布模式為核心的開(kāi)源庫(kù) ,EventBus翻譯過(guò)來(lái)是事件總線的意思,一個(gè)個(gè)事件(event)發(fā)送到總線上,然后EventBus根據(jù)已注冊(cè)的訂閱者(subscribers)來(lái)匹配相應(yīng)的事件,進(jìn)而把事件傳遞給訂閱者,這個(gè)就是典型的觀察者模式
EventBus GitHub地址
對(duì)比近似功能
對(duì)比廣播,這個(gè)框架的封裝了,沒(méi)有那么重量級(jí)吧個(gè)人理解差距不大,handler ,startActivityForResult()等。并且這個(gè)也和廣播類(lèi)似有個(gè)粘性的概念
使用
1.在Android Studio中添加如下依賴(lài):
compile 'org.greenrobot:eventbus:3.0.0'
2.創(chuàng)建事件實(shí)體類(lèi),事件實(shí)體類(lèi),就是傳遞的事件,一個(gè)組件向另一個(gè)組件發(fā)送的信息可以?xún)?chǔ)存在一個(gè)類(lèi)中,該類(lèi)就是一個(gè)事件,會(huì)被EventBus發(fā)送給訂閱者 ,
如果你想發(fā)送字符串可以這樣設(shè)置你的messageEvent構(gòu)造 string類(lèi)型:
EventBus.getDefault().post(new MessageEvent("Hello !....."));
public class MessageEvent {
private String message;
public MessageEvent(String message){
this.message = message;
}
public String getMessage(){
return message;
}
}
3.向EventBus注冊(cè),成為訂閱者以及解除注冊(cè)
EventBus.getDefault().register(this);
即可將當(dāng)前類(lèi)注冊(cè),成為訂閱者,即對(duì)應(yīng)觀察者模式的“觀察者”,一旦有事件發(fā)送過(guò)來(lái),該觀察者就會(huì)接收到匹配的事件。通常,在類(lèi)的初始化時(shí)便進(jìn)行注冊(cè),如果是Activity則在onCreate()方法內(nèi)進(jìn)行注冊(cè)。
當(dāng)訂閱者不再需要接受事件的時(shí)候,我們需要解除注冊(cè),釋放內(nèi)存:
EventBus.getDefault().unregister(this);
4.聲明訂閱方法
觀察者模式,觀察者有著一個(gè)update()方法,在接收到事件的時(shí)候會(huì)調(diào)用該update()方法,這個(gè)方法就是一個(gè)訂閱方法。在EventBus 3.0中,聲明一個(gè)訂閱方法需要用到@Subscribe注解,因此在訂閱者類(lèi)中添加一個(gè)有著@Subscribe注解的方法即可,方法名字可自定義,而且必須是public權(quán)限,其方法參數(shù)有且只能有一個(gè),另外類(lèi)型必須為第一步定義好的事件類(lèi)型(比如上面的MessageEvent),如下所示
@Subscribe
public void onEvent(MessageEvent event) {
/* Do something */
}
5.發(fā)送事件
與觀察者模式對(duì)應(yīng)的,當(dāng)有事件發(fā)生,需要通知觀察者的時(shí)候,被觀察者會(huì)調(diào)用notifyObservers()方法來(lái)通知所有已經(jīng)注冊(cè)的觀察者,在EventBus中,對(duì)觀察者模式底層進(jìn)行了封裝,我們只需要調(diào)用以下代碼就能把事件發(fā)送出去:
EventBus.getDefault().post(EventType eventType);
上面的5個(gè)步驟就完成了EventBus 訂閱發(fā)布了,可能大家比較陌生的就是@Subscribe注解
@Subscribe注解
訂閱方法,添加了@Subscribe注解,直接看他的代碼。按住點(diǎn)進(jìn)去
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
/**
* If true, delivers the most recent sticky event (posted with
* {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
*/
boolean sticky() default false;
/** Subscriber priority to influence the order of event delivery.
* Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
* others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
* delivery among subscribers with different {@link ThreadMode}s! */
int priority() default 0;
}
內(nèi)部有三個(gè)成員,分別是threadMode、sticky、priority。
threadMode代表訂閱方法所運(yùn)行的線程,
public enum ThreadMode {
POSTING,
MAIN,
BACKGROUND,
ASYNC
}
POSTING:表示訂閱方法運(yùn)行在發(fā)送事件的線程
MAIN:表示訂閱方法運(yùn)行在UI線程,由于UI線程不能阻塞,因此當(dāng)使用MAIN的時(shí)候,訂閱方法不應(yīng)該耗時(shí)過(guò)長(zhǎng)
BACKGROUND:表示訂閱方法運(yùn)行在后臺(tái)線程,如果發(fā)送的事件線程不是UI線程,那么就使用該線程;如果發(fā)送事件的線程是UI線程,那么新建一個(gè)后臺(tái)線程來(lái)調(diào)用訂閱方法
ASYNC:訂閱方法與發(fā)送事件始終不在同一個(gè)線程,即訂閱方法始終會(huì)使用新的線程來(lái)運(yùn)行。
一般都是下面的方式,因?yàn)槲覀円话愣际且耈I要回到主線程:
/訂閱方法,當(dāng)接收到事件的時(shí)候,會(huì)調(diào)用該方法
@Subscribe(threadMode = ThreadMode.MAIN)
sticky代表是否是粘性事件,下面再說(shuō)
priority代表優(yōu)先級(jí)。設(shè)置該優(yōu)先級(jí)的目的是,當(dāng)一個(gè)事件有多個(gè)訂閱者的時(shí)候,優(yōu)先級(jí)高的會(huì)優(yōu)先接收到事件。給這個(gè)三個(gè)成員賦不同的值,能使得訂閱方法有著不同的效果。
sticky解釋
關(guān)于粘性事件,可以參考Android的廣播機(jī)制,其中有一個(gè)粘性廣播,粘性廣播的意思是:該廣播發(fā)送后,會(huì)保存在內(nèi)存中,如果后來(lái)有注冊(cè)的Receiver與之匹配,那么該Receiver便會(huì)接收到該廣播。那么粘性事件同理,在注冊(cè)之前便把事件發(fā)生出去,等到注冊(cè)之后便會(huì)收到最近發(fā)送的粘性事件(必須匹配)。注意:只會(huì)接收到最近發(fā)送的一次粘性事件,之前的會(huì)接受不到
如果發(fā)送了3個(gè)sticky事件,同一個(gè)訂閱者只會(huì)收到最后一個(gè)!!!!切記,可以聯(lián)系觀察者模式記憶,觀察者是做出三次改變 ,會(huì)響應(yīng)3次,但是這里不會(huì),只會(huì)執(zhí)行最后一次!!!!
結(jié)果親測(cè),版本有限就不貼出了。只會(huì)接受到最后發(fā)送的粘性事件,在此之前的事件都接收不到!!!
sticky在實(shí)際項(xiàng)目中用到的場(chǎng)景
我們公司項(xiàng)目做的基金模塊頁(yè)面就是頂部有多個(gè)tab 沒(méi)個(gè)tab 的頭部都有一個(gè)基金購(gòu)買(mǎi)風(fēng)險(xiǎn)的提示,用戶(hù)在這6個(gè)tab 每個(gè)頁(yè)面是不同的,但是都存在這個(gè),現(xiàn)在需求就是我點(diǎn)擊任意頁(yè)面的提示 表明我知道這個(gè)事情了,然后在其他5個(gè)頁(yè)面都不顯示了,這個(gè)時(shí)候就用的是sticky發(fā)送事件