本篇文章主要講解關(guān)于EventBus的使用,下篇文章會(huì)根據(jù)EventBus的使用具體講解其中的原理下硕。雖然現(xiàn)在RxJava也可以實(shí)現(xiàn)EventBus的功能丁逝,但原理性的東西都是一樣的。
一梭姓、EventBus簡(jiǎn)介
EventBus是一個(gè)Android端優(yōu)化的publish/subscribe消息總線霜幼,簡(jiǎn)化了應(yīng)用程序內(nèi)各組件間、組件與后臺(tái)線程間的通信誉尖。
作為一個(gè)消息總線主要有三個(gè)組成部分:
事件(Event):可以是任意類型的對(duì)象罪既。通過事件的發(fā)布者將事件進(jìn)行傳遞。
事件訂閱者(Subscriber):接收特定的事件。
事件發(fā)布者(Publisher):用于通知 Subscriber 有事件發(fā)生萝衩』赝欤可以在任意線程任意位置發(fā)送事件。
上圖解釋了整個(gè)EventBus的大概工作流程:事件的發(fā)布者(Publisher)將事件(Event)通過post()方法發(fā)送猩谊。EventBus內(nèi)部進(jìn)行處理千劈,找到訂閱了該事件(Event)的事件訂閱者(Subscriber)。然后該事件的訂閱者(Subscriber)通過onEvent()方法接收事件進(jìn)行相關(guān)處理(關(guān)于onEvent()在EventBus 3.0中有改動(dòng)牌捷,下面詳細(xì)說明)墙牌。
二、EventBus的簡(jiǎn)單使用
1暗甥、把EventBus依賴到項(xiàng)目
build.gradle添加引用
compile 'de.greenrobot:eventbus:3.0.0-beta1'
2喜滨、構(gòu)造事件(Event)對(duì)象。也就是發(fā)送消息類
每一個(gè)消息類撤防,對(duì)應(yīng)一種事件虽风。這里我們定義兩個(gè)消息發(fā)送類。后面講解具體作用寄月。
public class NewsEvent {
private String message;
public NewsEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
public class ToastEvent {
private String content;
public ToastEvent(String content) {
this.content = content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
3辜膝、注冊(cè)/解除事件訂閱(Subscriber)
EventBus.getDefault().register(this);//注冊(cè)事件 其中this代表訂閱者
具體注冊(cè)了對(duì)什么事件的訂閱,這個(gè)需要onEvent()方法來說明漾肮。在EventBus 3.0之前厂抖,onEvent()方法是用來接收指定事件(Event)類型對(duì)象,然后進(jìn)行相關(guān)處理操作克懊。在EventBus 3.0之后忱辅,onEvent()方法可以自定義方法名,不過要加入注解@Subscribe谭溉。
@Subscribe
public void onToastEvent(ToastEvent event){
Toast.makeText(MainActivity.this,event.getContent(),Toast.LENGTH_SHORT).show();
}
通過register(this)來表示該訂閱者進(jìn)行了訂閱墙懂,通過onToastEvent(ToastEvent event)表示指定對(duì)事件ToastEvent的訂閱。到這里訂閱就完成了夜只。
需要注意的是:一般在onCreate()方法中進(jìn)行注冊(cè)訂閱垒在。在onDestory()方法中進(jìn)行解除訂閱。
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
4 扔亥、發(fā)送消息
訂閱已經(jīng)完成,那么便可以發(fā)送訂閱了谈为。
EventBus.getDefault().post(new ToastEvent("Toast,發(fā)個(gè)提示旅挤,祝大家新年快樂!"));
那么onToastEvent(ToastEvent event)會(huì)收到事件伞鲫,并彈出提示粘茄。
EventBus的基礎(chǔ)使用流程就是這樣的。
其實(shí),EventBus還有好多其他的功能柒瓣。下面我們一個(gè)個(gè)介紹儒搭。
三、EventBus的進(jìn)階使用
1.線程模式ThreadMode
當(dāng)你接收的的事件后芙贫,如果處于非UI線程搂鲫,你要更新UI怎么辦?如果處于UI線程磺平,你要進(jìn)行耗時(shí)操作魂仍,怎么辦?等等其他情況,通過ThreadMode統(tǒng)統(tǒng)幫你解決拣挪。
用法展示:
@Subscribe(threadMode = ThreadMode.MainThread)
public void onNewsEvent(NewsEvent event){
String message = event.getMessage();
mTv_message.setText(message);
}
使用起來很簡(jiǎn)單擦酌,通過@Subscribe(threadMode = ThreadMode.MainThread)
即可指定。
下面具體介紹下ThreadMode菠劝。
關(guān)于ThreadMode赊舶,一共有四種模式PostThread,PostThread赶诊,BackgroundThread以及Async笼平。
PostThread:事件的處理在和事件的發(fā)送在相同的進(jìn)程,所以事件處理時(shí)間不應(yīng)太長(zhǎng)甫何,不然影響事件的發(fā)送線程出吹。
**MainThread: **事件的處理會(huì)在UI線程中執(zhí)行。事件處理時(shí)間不能太長(zhǎng)辙喂,這個(gè)不用說的捶牢,長(zhǎng)了會(huì)ANR的。
BackgroundThread:如果事件是在UI線程中發(fā)布出來的巍耗,那么事件處理就會(huì)在子線程中運(yùn)行秋麸,如果事件本來就是子線程中發(fā)布出來的,那么事件處理直接在該子線程中執(zhí)行炬太。所有待處理事件會(huì)被加到一個(gè)隊(duì)列中灸蟆,由對(duì)應(yīng)線程依次處理這些事件,如果某個(gè)事件處理時(shí)間太長(zhǎng)亲族,會(huì)阻塞后面的事件的派發(fā)或處理炒考。
Async:事件處理會(huì)在單獨(dú)的線程中執(zhí)行,主要用于在后臺(tái)線程中執(zhí)行耗時(shí)操作霎迫,每個(gè)事件會(huì)開啟一個(gè)線程斋枢。
2.priority事件優(yōu)先級(jí)
事件的優(yōu)先級(jí)類似廣播的優(yōu)先級(jí),優(yōu)先級(jí)越高優(yōu)先獲得消息知给。
用法展示:
@Subscribe(priority = 100)
public void onToastEvent(ToastEvent event){
Toast.makeText(MainActivity.this,event.getContent(),Toast.LENGTH_SHORT).show();
}
當(dāng)多個(gè)訂閱者(Subscriber)對(duì)同一種事件類型進(jìn)行訂閱時(shí)瓤帚,即對(duì)應(yīng)的事件處理方法中接收的事件類型一致描姚,則優(yōu)先級(jí)高(priority 設(shè)置的值越大),則會(huì)先接收事件進(jìn)行處理戈次;優(yōu)先級(jí)低(priority 設(shè)置的值越行薄),則會(huì)后接收事件進(jìn)行處理怯邪。
除此之外绊寻,EventBus也可以終止對(duì)事件繼續(xù)傳遞的功能。
用法展示:
@Subscribe(priority = 100)
public void onToastEvent(ToastEvent event){
Toast.makeText(MainActivity.this,event.getContent(),Toast.LENGTH_SHORT).show();
EventBus.getDefault().cancelEventDelivery(event);
}
這樣其他優(yōu)先級(jí)比100低擎颖,并且訂閱了該事件的訂閱者就會(huì)接收不到該事件榛斯。
3.EventBus黏性事件
EventBus除了普通事件也支持粘性事件÷酰可以理解成:訂閱在發(fā)布事件之后驮俗,但同樣可以收到事件。訂閱/解除訂閱和普通事件一樣允跑,但是處理訂閱的方法有所不同王凑,需要注解中添加sticky = true。
用法展示:
@Subscribe(priority = 100,sticky = true)
public void onToastEvent(ToastEvent event){
Toast.makeText(MainActivity.this,event.getContent(),Toast.LENGTH_SHORT).show();
EventBus.getDefault().cancelEventDelivery(event);
}
這樣聋丝,假設(shè)一個(gè)ToastEvent 的事件已經(jīng)發(fā)布索烹,此時(shí)還沒有注冊(cè)訂閱。當(dāng)設(shè)置了sticky = true弱睦,在ToastEvent 的事件發(fā)布后百姓,進(jìn)行注冊(cè)。依然能夠接收到之前發(fā)布的事件况木。
不過這個(gè)時(shí)候垒拢,發(fā)布事件的方式就改變了。
EventBus.getDefault().postSticky(new ToastEvent("Toast,發(fā)個(gè)提示火惊,祝大家新年快樂求类!"));
我們?nèi)绻辉傩枰撜承允录覀兛梢砸瞥?/p>
EventBus.getDefault().removeStickyEvent(ToastEvent.class);
或者調(diào)用移除所有粘性事件
EventBus.getDefault().removeAllStickyEvents();
4.EventBus配置
EventBus在2.3版本中添加了EventBuilder去配置EventBus的各方各面。
比如:如何去構(gòu)建一個(gè)在發(fā)布事件時(shí)沒有訂閱者時(shí)保持沉默的EventBus屹耐。
EventBus eventBus = EventBus.builder()
.logNoSubscriberMessages(false)
.sendNoSubscriberEvent(false)
.build();
通過上述設(shè)置尸疆,當(dāng)一個(gè)事件沒有訂閱者時(shí),不會(huì)輸出log信息惶岭,也不會(huì)發(fā)布一條默認(rèn)信息寿弱。
配置默認(rèn)的EventBus實(shí)例,使用EventBus.getDefault()是一個(gè)簡(jiǎn)單的方法按灶。獲取一個(gè)單例的EventBus實(shí)例脖捻。EventBusBuilder也允許使用installDefaultEventBus方法去配置默認(rèn)的EventBus實(shí)例。
注意:不同的EventBus 的對(duì)象的數(shù)據(jù)是不共享的兆衅。通過一個(gè)EventBus 對(duì)象去發(fā)布事件,只有通過同一個(gè)EventBus 對(duì)象訂閱事件,才能接收該事件羡亩。所以以上使用EventBus.getDefault()獲得的都是同一個(gè)實(shí)例摩疑。
下面用一個(gè)小栗子來展示下EventBus的應(yīng)用。
以上就是本篇文章的內(nèi)容畏铆。下一篇文章將從源碼的角度來分析EventBus的使用雷袋。喜歡就給個(gè)贊吧,謝謝支持辞居。馬上就要過年了楷怒,祝大家新年快樂!