EventBus使用大全

近來在看平凡的世界,一發(fā)不可收拾夯巷,非常震撼心靈,心里面的那種觸動(dòng)我真的表達(dá)不清楚哀墓。已經(jīng)很久沒有看到這么好看的電視劇了趁餐。如果你還沒看過,我推薦大家可以去看一看麸祷。

前段時(shí)間有人問我澎怒,fragment 怎么與 activity 通信?同級(jí)下的 fragment 之間的通信阶牍?

對(duì)于這個(gè)問題有很多方案喷面,我簡單的說幾種,可能還有更好的方案走孽。

  • 宿主 onAttach 方法獲取到 activity 實(shí)例惧辈,有了實(shí)例就是調(diào)用方法的問題了。注意不同的 fragment 之間需要強(qiáng)轉(zhuǎn)磕瓷。

  • 接口

  • 廣播 (有點(diǎn)大題小用了)

  • handler

  • EventBus盒齿,RxBus,Otto

五種方案各有優(yōu)缺點(diǎn)困食,在項(xiàng)目當(dāng)中根據(jù)具體情況靈活應(yīng)用边翁。這里主要講解 EventBus 在項(xiàng)目中的使用潦刃,雖然 EventBus 可以很方便的實(shí)現(xiàn)模塊與模塊之間的通信响鹃,如果頻繁的使用可能導(dǎo)致代碼錯(cuò)亂肝陪。這點(diǎn)對(duì)于初學(xué)者尤為重要糙及。下面一起來看看 EventBus 一些常用的使用方法。

什么是EventBus

EventBus是一個(gè) 發(fā)布/訂閱 模式的消息總線庫惋戏,它簡化了應(yīng)用程序內(nèi)各組件間潭苞、組件與后臺(tái)線程間的通信慌随,解耦了事件的發(fā)送者和接收者垛贤,避免了復(fù)雜的焰坪、易于出錯(cuò)的依賴及生命周期問題,可以使我們的代碼更加簡潔聘惦、健壯某饰。EventBus 用于各組件通信,那么用于 fragment 之間的通信就非常合適了。

相關(guān)文章:

初談一Java Annotation

EventBus的基本使用

EventBus的github地址

項(xiàng)目依賴

gradle依賴:

appbuild.gradle文件下:

dependencies {
 compile 'org.greenrobot:eventbus:3.0.0'
 }

接著來擼一擼 EventBus 的使用步驟:

  • 1露乏、 定義事件
  • 2碧浊、 訂閱
  • 3、 發(fā)布事件

1瘟仿、定義事件

MessageEvent 為例:

public class MessageEvent {
    
    public String message;

    public MessageEvent(String message) {
        this.message = message;
    }
}

訂閱

聲明訂閱方法,并且指定線程模式(默認(rèn)主線程)比勉。

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent event) {
        Toast.makeText(this,"你好EventBus"+event.message,Toast.LENGTH_SHORT).show();
    };

注意 @Subscribe annotation 是不可缺少的劳较,onMessageEvent方法名可以隨意命名。

activityfragment 注冊(cè)和注銷 EventBus

onCreate注冊(cè):

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }
    }

onStart注冊(cè):

    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

onDestroy注銷:

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

發(fā)布事件

最后即是事件源發(fā)布事件浩聋。我們可以在代碼的任何位置發(fā)布事件观蜗,當(dāng)前所有事件類型與發(fā)布的事件類型匹配的訂閱者都將收到它。其實(shí)內(nèi)部是以 map 來存儲(chǔ)事件衣洁,map的鍵就是事件類名(這里就是MessageEvent作為鍵值)墓捻,在發(fā)布相同事件源的時(shí)候避免多次處理。

 EventBus.getDefault().post(new MessageEvent(""));

下面來看一個(gè)簡單的案例(通過點(diǎn)擊按鈕來發(fā)步事件源):

    public void click_event(View view) {
        EventBus.getDefault().post(new MessageEvent("雞年大吉"));
    }

效果圖一覽:

bus

源碼我會(huì)在文章的最后給出坊夫。

Sticky事件

Sticky事件被我稱之為粘性事件砖第,功能類似sticky broadcast(粘性廣播)。就是某些事件攜帶的信息在事件被發(fā)布之后依然有價(jià)值环凿。比如梧兼,當(dāng)前 activity 發(fā)布了事件源,新啟的 activity 對(duì)該事件進(jìn)行訂閱智听,同樣能夠處理羽杰。

發(fā)布粘性事件:

        EventBus.getDefault().postSticky(new MessageEvent("大吉大利"));

處理粘性事件:

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onMessageEvent(MessageEvent event) {
    
        Toast.makeText(this, "接收A發(fā)來的消息" + event.message, Toast.LENGTH_SHORT).show();
    }

注意 sticky 成員設(shè)置為 true,默認(rèn)為 false到推。

運(yùn)行效果圖:

bus

源碼會(huì)在文章最后附上

最新的sticky事件會(huì)在注冊(cè)時(shí)立即自動(dòng)地被傳遞給匹配的訂閱者考赛。但有時(shí)手動(dòng)地去檢查sticky事件可能會(huì)更方便一些。有時(shí)也可能需要移除(消費(fèi))sticky事件以便于它不會(huì)再被傳遞莉测。

移除sticky事件:

   MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
   if (stickyEvent != null) {
       EventBus.getDefault().removeStickyEvent(stickyEvent);
   }

查看源碼我們知道removeStickyEvent方法是重載的颜骤,當(dāng)傳遞class時(shí),它將返回持有的之前的sticky事件悔雹。也可以使用如下變體進(jìn)行處理:

    MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class);
        if (stickyEvent != null) {
            //handler
        }

優(yōu)先級(jí)

我們可以通過優(yōu)先級(jí)來改變事件傳遞的順序复哆。

    @Subscribe(priority = 1)
    public void onEvent(MessageEvent event) {

    }

在相同的傳遞線程內(nèi)(ThreadMode),優(yōu)先級(jí)越高的訂閱者越先接收到事件腌零。默認(rèn)優(yōu)先級(jí)為0梯找。在不同線程(ThreadMode)中優(yōu)先級(jí)并不會(huì)影響事件的傳遞順序。

取消事件

有時(shí)我們需要取消事件的傳遞:

    @Subscribe()
    public void onMessageEvent(MessageEvent event) {
        //處理事件...


        //取消事件
        EventBus.getDefault().cancelEventDelivery(event) ;
    }

所有后續(xù)的事件傳遞將被取消益涧,后面的訂閱者將無法接收到事件锈锤。cancelEventDelivery方法只接收(Object event)參數(shù),那么我們只能在訂閱者的事件處理方法中調(diào)用。

傳遞線程

事件可以在不同于拋出事件的線程中傳遞久免。一個(gè)很常見的例子浅辙,獲取網(wǎng)絡(luò)數(shù)據(jù)更新UI。網(wǎng)絡(luò)阎姥,耗時(shí)的操作必然是異步操作记舆,更新 UI 則在 UI 線程操作。

EventBus的傳遞線程類型有四類:

  • ThreadMode.POSTING(默認(rèn))
  • ThreadMode.MAIN (主線程)
  • ThreadMode.BACKGROUND (后臺(tái)線程)
  • ThreadMode.ASYNC (異步線程)

ThreadMode.POSTING

默認(rèn)方式呼巴,訂閱者將在與拋出事件相同的線程中被調(diào)用泽腮。事件傳遞是同步完成的,事件傳遞完成時(shí)衣赶,所有的訂閱者將已經(jīng)被調(diào)用了一次诊赊。這個(gè)ThreadMode意味著最小的開銷,因?yàn)樗耆苊饬司€程的切換府瞄。鑒于以上的特點(diǎn)碧磅,那么可以用于已知耗時(shí)非常短的簡單的不需要請(qǐng)求主線程的任務(wù),可以采用該模式遵馆。使用這個(gè)模式的事件處理器應(yīng)該迅速返回以避免阻塞發(fā)布事件的線程鲸郊,而后者可能是主線程。比如:

    @Subscribe(threadMode = ThreadMode.POSTING)
    public void onMessage(MessageEvent event) {
        //handler事件
        Toast.makeText(this, "你好EventBus" + event.message, Toast.LENGTH_SHORT).show();
    }

ThreadMode.MAIN

訂閱者將在主線程(UI線程)中被調(diào)用团搞。如果發(fā)布事件的線程是主線程严望,事件處理器方法將會(huì)直接被調(diào)用。事件處理器使用這個(gè)模式必須快速地返回以避免阻塞主線程逻恐。

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessage(MessageEvent event) {
        //處理事件
    }

ThreadMode.BACKGROUND

訂閱者將在一個(gè)后臺(tái)線程中被調(diào)用像吻。如果發(fā)布事件的線程不是主線程,事件處理器方法將在該線程中被調(diào)用复隆;反之拨匆,EventBus使用一個(gè)單獨(dú)的后臺(tái)線程,它將順序地傳遞它所有的事件挽拂。使用該模式的事件處理器應(yīng)該嘗試快速返回以避免阻塞后臺(tái)線程惭每。

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void onMessage(MessageEvent event) {
        //handler事件
    }

ThreadMode.ASYNC

訂閱者將在另外一個(gè)線程中被調(diào)用。這里的另外一個(gè)線程不等同于發(fā)布事件的線程和UI線程亏栈。用于處理比較耗時(shí)的操作台腥,如訪問網(wǎng)絡(luò),數(shù)據(jù)庫操作绒北。

    @Subscribe(threadMode = ThreadMode.ASYNC)
    public void onMessage(MessageEvent event) {
        //handler事件
    }

EventBus 原理這里就不在深入黎侈,EventBus 真的非常棒,值得你擁有闷游。

源碼地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末峻汉,一起剝皮案震驚了整個(gè)濱河市贴汪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌休吠,老刑警劉巖扳埂,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異瘤礁,居然都是意外死亡阳懂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門蔚携,熙熙樓的掌柜王于貴愁眉苦臉地迎上來希太,“玉大人,你說我怎么就攤上這事酝蜒。” “怎么了矾湃?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵亡脑,是天一觀的道長。 經(jīng)常有香客問我邀跃,道長霉咨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任拍屑,我火速辦了婚禮途戒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘僵驰。我一直安慰自己喷斋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布蒜茴。 她就那樣靜靜地躺著星爪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪粉私。 梳的紋絲不亂的頭發(fā)上顽腾,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音诺核,去河邊找鬼抄肖。 笑死,一個(gè)胖子當(dāng)著我的面吹牛窖杀,可吹牛的內(nèi)容都是我干的漓摩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼陈瘦,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼幌甘!你這毒婦竟也來了潮售?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤锅风,失蹤者是張志新(化名)和其女友劉穎酥诽,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體皱埠,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肮帐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了边器。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片训枢。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖忘巧,靈堂內(nèi)的尸體忽然破棺而出恒界,到底是詐尸還是另有隱情,我是刑警寧澤砚嘴,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布十酣,位于F島的核電站,受9級(jí)特大地震影響际长,放射性物質(zhì)發(fā)生泄漏耸采。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一工育、第九天 我趴在偏房一處隱蔽的房頂上張望虾宇。 院中可真熱鬧,春花似錦如绸、人聲如沸嘱朽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽燥翅。三九已至,卻和暖如春蜕提,著一層夾襖步出監(jiān)牢的瞬間森书,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工谎势, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凛膏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓脏榆,卻偏偏與公主長得像猖毫,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子须喂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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

  • EventBus 是一個(gè)Android端優(yōu)化的 publish/subscribe 消息總線,簡化了應(yīng)用程序各個(gè)組...
    王世軍Steven閱讀 1,852評(píng)論 4 21
  • EventBus是一個(gè) 發(fā)布/訂閱 模式的消息總線庫吁断,它簡化了應(yīng)用程序內(nèi)各組件間趁蕊、組件與后臺(tái)線程間的通信,解耦了事...
    hanpfei閱讀 4,051評(píng)論 0 50
  • 前言:EventBus出來已經(jīng)有一段時(shí)間了仔役,github上面也有很多開源項(xiàng)目中使用了EventBus掷伙。所以抽空學(xué)習(xí)...
    Kerry202閱讀 1,286評(píng)論 1 2
  • 先吐槽一下博客園的MarkDown編輯器,推出的時(shí)候還很高興博客園支持MarkDown了又兵,試用了下發(fā)現(xiàn)支持不完善就...
    Ten_Minutes閱讀 563評(píng)論 0 2
  • 進(jìn)入單位近三年任柜,一直在鄉(xiāng)下基層,我那些三姑六婆以及朋友都會(huì)經(jīng)常給我嘮叨:快點(diǎn)想辦法調(diào)回市里了沛厨,就算不到市里也到...
    袁洪yanh閱讀 244評(píng)論 0 1