EventBus 3.0

入門

簡介

GitHub:EventBus

Android optimized event bus that simplifies communication between Activities, Fragments, Threads, Services, etc. Less code, better quality.

android最佳的事件總線,簡化了Activities、Fragments、Threads、Services等之間的通信,代碼更少,質量更好。

EventBus

EventBus是greenrobot團隊Markus Junginger開源的發布-訂閱事件總線庫。主要用于:適合當做組件間的通訊工具使用,主要用來傳遞消息。請求網絡,等網絡返回時通過Handler或Broadcast通知UI,兩個Fragment之間需要通過Listener通信,這些需求都可以通過EventBus實現。。。。

優點有

簡潔性。簡化了應用程序內各組件間、組件與后臺線程間的通信。
開銷小。代碼更優雅。
低耦合。將發送者和接受者解耦。

缺點是

事件一般都要寫個對應的 Event 類出來,導致會都很多這些類;
可讀性降低。兩個模塊間交互,不如原來定位快。
EventBus3.0較之前版本:用注解的方式代替約定的方法名規范。

其他框架對比

RxBus:使用RxJava實現的庫。缺點有:如何實現sticky功能;如何處理RxJava的訂閱操作中的異常導致的訂閱的中斷(因為RxJava中出現異常會直接跳轉OnError,事件流就被中斷了);使用運行時(Run-time)注解的話,反射的性能問題。

Guava:Google的Guava是一個龐大的庫,EventBus只是它附帶的一個小功能,因此實際項目中使用并不多。

Otto:square的otto修改自 Guava。但已停止維護,臨死前推薦大家使用RxBus。

基礎用法

使用

基本使用大致分為5個步驟:

1,創建事件類;(用一個POJO封裝傳遞數據。如果是簡單的基本數據類型,不封裝也行。)

2,在訂閱事件處注冊事件;(在發送端)

EventBus.getDefault().register(this);

3,發送事件;(此為發布者,在發送端)

EventBus.getDefault().post(new EventPOJO("Hello EventBus!"));

4,接收,處理事件;(此為訂閱者,在接收端)

//接收方法可以隨便起名,但需要添加Subscribe注解。
@Subscribe(threadMode= ThreadMode.MAIN)

public voidonEvent(EventPOJO messageEvent) {

    tv_message.setText(messageEvent.getMessage());

}

5,注銷總線。

EventBus.getDefault().unregister(this);

@Subscribe

ThreadMode提供了四種類型。MainThread 主線程,BackgroundThread 后臺線程,Async 后臺線程,PostThread 發送線程(默認)。

  1. POSTING(默認):如果使用事件處理函數指定了線程模型為POSTING,那么該事件在哪個線程發布出來的,事件處理函數就會在這個線程中運行,也就是說發布事件和接收事件在同一個線程。在線程模型為POSTING的事件處理函數中盡量避免執行耗時操作,因為它會阻塞事件的傳遞,甚至有可能會引起ANR。
  2. MAIN:事件的處理會在UI線程中執行。事件處理時間不能太長,長了會ANR的。
  3. BACKGROUND:如果事件是在UI線程中發布出來的,那么該事件處理函數就會在新的線程中運行,如果事件本來就是子線程中發布出來的,那么該事件處理函數直接在發布事件的線程中執行。在此事件處理函數中禁止進行UI更新操作。
  4. ASYNC:無論事件在哪個線程發布,該事件處理函數都會在新建的子線程中執行,同樣,此事件處理函數中禁止進行UI更新操作。

sticky機制

sticky機制俗稱粘性事件。即發送事件之后再訂閱該事件也能收到該事件。sticky默認值為false,在Subscribe方法中可以更改。

@Subscribe(threadMode = ThreadMode.POSTING,priority = 1, sticky = true)

priority 值表示優先級。值越小優先級越低,默認為0。

1,訂閱粘性事件;

bt_subscription.setOnClickListener(newView.OnClickListener() {
    @OverridepublicvoidonClick(View v) {//注冊事件
        EventBus.getDefault().register(MainActivity.this);
    }
});

2,處理粘性事件;

@Subscribe(threadMode = ThreadMode.POSTING,priority=0, sticky =true)
publicvoidononMoonStickyEvent(MessageEvent messageEvent){
    tv_message.setText(messageEvent.getMessage());
}

3,發送粘性事件。

bt_subscription.setOnClickListener(newView.OnClickListener() {
    @OverridepublicvoidonClick(View v) {
        EventBus.getDefault().postSticky(newMessageEvent("粘性事件"));
        finish();
    }
});

進階用法

添加processor

由于使用了注解,性能會降低。使用processor在編譯的時候為注冊類構建了一個索引,而不是在運行時,這樣的結果是其讓EventBus 3.0的性能提升了一倍,相比2.4來說,其會是它的3到6倍。

EventBus性能對比

使用processor有兩種方案。<一>添加依賴:provided'de.greenrobot:eventbus-annotation-processor:3.0.0-beta1';
<二>添加依賴:apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'。在Application中添加EventBus.builder().addIndex(newMyEventBusIndex()).installDefaultEventBus();。

源碼解析

EventBus是用了反射,并且維護了一個全局map,記錄event到method的映射。

通過注解把類中的所有訂閱者和訂閱信息提取出來,這里有很多過濾條件保證提取的正確性。

EventBus中有兩個映射表,subscriptionsByEventType中存放所有event和對應的訂閱者,typesBySubscriber中存放每個訂閱者對應的事件。提取出來的訂閱者和信息就被存進了這兩個表里。

private final Map<Class<?>, CopyOnWriteArrayList<Subscription>>

subscriptionsByEventType;

private final Map<Object, List<Class<?>>> typesBySubscriber;

所有的的poster被放在3個隊列中,mainThreadPoster、backgroundPoster、asyncPoster。這3個隊列是用鏈表實現的,讓poster在各自的線程排隊,等候處理。如果是POSTING類型的事件,就直接執行了,不用排隊。

錯誤匯總

post了消息之后,你的訂閱者有多個,每一個都接收嗎?能否做到指定接收者。

使用經驗

EventBus最好都定義在一個包下,分散開后期不好維護。

參考文章

Android事件總線(一)EventBus3.0用法全解析 劉望舒

EventBus使用詳解

EventBus 3.0的用法詳解(一)

EventBus3.0源碼解析

老司機教你“飆”EventBus3

快速Android開發系列通信篇之EventBus

EventBus使用詳解(一)——初步使用EventBus 講的2.X,算的上比較早的blog了。貼上紀念下。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376