關(guān)于EventBus荞膘,從使用到解析(上)

本篇文章主要講解關(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è)贊吧,謝謝支持辞居。馬上就要過年了楷怒,祝大家新年快樂!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瓦灶,一起剝皮案震驚了整個(gè)濱河市鸠删,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贼陶,老刑警劉巖刃泡,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異碉怔,居然都是意外死亡烘贴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門撮胧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來桨踪,“玉大人,你說我怎么就攤上這事芹啥《屠耄” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵叁征,是天一觀的道長(zhǎng)纳账。 經(jīng)常有香客問我,道長(zhǎng)捺疼,這世上最難降的妖魔是什么疏虫? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮啤呼,結(jié)果婚禮上卧秘,老公的妹妹穿的比我還像新娘。我一直安慰自己官扣,他們只是感情好翅敌,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惕蹄,像睡著了一般蚯涮。 火紅的嫁衣襯著肌膚如雪治专。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天遭顶,我揣著相機(jī)與錄音张峰,去河邊找鬼。 笑死棒旗,一個(gè)胖子當(dāng)著我的面吹牛喘批,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铣揉,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼饶深,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了逛拱?” 一聲冷哼從身側(cè)響起敌厘,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎橘券,沒想到半個(gè)月后额湘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡旁舰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年锋华,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片箭窜。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡毯焕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出磺樱,到底是詐尸還是另有隱情纳猫,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布竹捉,位于F島的核電站芜辕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏块差。R本人自食惡果不足惜侵续,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望憨闰。 院中可真熱鬧状蜗,春花似錦、人聲如沸鹉动。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)泽示。三九已至缸血,卻和暖如春蜜氨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背属百。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工记劝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人族扰。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像定欧,于是被迫代替她去往敵國(guó)和親渔呵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容