翻了一遍EventBus官方文檔

EventBus事件總線(xiàn).以觀察者模式實(shí)現(xiàn),消息推送/訂閱.用于Android組件之間相互通信

Note:文章基于EventBus3.0

Paste_Image.png

項(xiàng)目地址:https://github.com/greenrobot/EventBus
Docments:http://greenrobot.org/eventbus/documentation/how-to-get-started/

先來(lái)聊聊:什么是通信?

Wiki中國(guó): 通信是發(fā)送者通過(guò)某種媒體以某種格式來(lái)傳遞信息到收信者以達(dá)致某個(gè)目的。在古代馏锡,人們通過(guò)驛站憎蛤、飛鴿傳書(shū)果善、烽火報(bào)警踪旷、符號(hào)逞盆、語(yǔ)言刊懈、眼神绿饵、觸碰等方式進(jìn)行信息傳遞。到了今天垄懂,隨著科技水平的飛速發(fā)展骑晶,通信基本完全利用有線(xiàn)或無(wú)線(xiàn)電完成,相繼出現(xiàn)了有線(xiàn)電話(huà)草慧、固定電話(huà)透罢、無(wú)線(xiàn)電話(huà)手機(jī)冠蒋、互聯(lián)網(wǎng)甚至視頻電話(huà)等各種通信方式羽圃。通信技術(shù)拉近了人與人之間的距離,提高了通信的效率抖剿,深刻的改變了人類(lèi)的通信朽寞。交流也是一種方法讓其他人理解你。

上面是Wiki的解釋,通信本身是個(gè)很抽象,寬泛的詞, 你跟朋友打個(gè)電話(huà)叫通信, 發(fā)個(gè)Email也叫通信, 兩個(gè)App之間傳數(shù)據(jù)也叫通信,也叫為進(jìn)程間通信, Activity和Activity之間傳遞數(shù)據(jù)叫組件間通信, 說(shuō)到這里,來(lái)下個(gè)通俗點(diǎn)的定義:一個(gè)東西給另一個(gè)東西傳遞東西(數(shù)據(jù)),就叫通信.

EventBus有什么用?解決了什么問(wèn)題?

方便Android組件間相互通信.在Activity,Service,Fragment之間傳遞數(shù)據(jù),例如,你在個(gè)人主頁(yè)編輯頭像的界面修改了頭像,這時(shí)候其它頁(yè)面的頭像也需要去修改,這時(shí)候可以試試EventBus.
基于觀察者模式:這個(gè)好理解, 有消息的發(fā)送者,也有消息的接收者,當(dāng)然,也可以是一發(fā)送者對(duì)應(yīng)多個(gè)接收者, EventBus使用起來(lái)非常簡(jiǎn)單,可以用來(lái)提供廣播之類(lèi)

怎么用?

  • 添加依賴(lài)
  • 使用三歩曲:
    • 定義事件類(lèi)
    • 注冊(cè)事件
    • 發(fā)送事件

添加依賴(lài)

  compile 'org.greenrobot:eventbus:3.0.0'

使用三步曲:

1,定義事件類(lèi)

事件類(lèi)是通信過(guò)程中的數(shù)據(jù)的載體,用來(lái)傳遞數(shù)據(jù),這里寫(xiě)一個(gè)最簡(jiǎn)單的事件類(lèi),后面說(shuō)如何傳遞數(shù)據(jù)

public static class MessageEvent {
  /* Additional fields if needed */
}

2.注冊(cè)事件

上面提到數(shù)據(jù)的發(fā)送者和接收者, 注冊(cè)事件是針對(duì)接收者的, 哪個(gè)組件需要接收消息,就在哪個(gè)組件中去注冊(cè)

  • 注冊(cè): EventBus.getDefault().register(this);
  • 添加函數(shù)注解@Subscribe:當(dāng)數(shù)據(jù)的發(fā)送者發(fā)出消息后,添加這個(gè)注解的函數(shù)會(huì)被調(diào)用
  • 添加@Subscribe注解的函數(shù)參數(shù),寫(xiě)上接收事件類(lèi)型,表示這個(gè)組件會(huì)接收這類(lèi)事件的消息
  • 注銷(xiāo):EventBus:EventBus.getDefault().unregister(this);

Note:一個(gè)事件是可以有多個(gè)接收者(訂閱者)

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  //注冊(cè)
  EventBus.getDefault().register(this);
}
//加上Subscribe注解,這個(gè)方法會(huì)在事件發(fā)出后收到回調(diào),方法名是自定義的
@Subscribe
public void onMessageEvent(MessageEvent event) {
  Log.i(TAG, "onMessageEvent: ");
}

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

3.發(fā)送事件

最后,消息的發(fā)送者發(fā)送事件, 這時(shí)候上面添加@Subscribe注解的函數(shù)會(huì)被調(diào)用

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

這時(shí)候在回來(lái)看這張大圖,So easy,點(diǎn)擊查看大圖

Paste_Image.png

這里順便吐槽下官方示例代碼:


Paste_Image.png

如果你打算把注冊(cè)寫(xiě)在onStart中,請(qǐng)?jiān)谇懊婕由吓袛?/p>

@Override
public void onStart() {
  super.onStart();
  if (!EventBus.getDefault().isRegistered(this)) {
    EventBus.getDefault().register(this);
  }
}

上面是EventBus的基本使用流程,其實(shí)這才開(kāi)始:

  • 在事件中傳遞數(shù)據(jù)
  • 指定事件接收線(xiàn)程
  • 發(fā)送黏性事件Sticky Events
  • 接收事件的優(yōu)先級(jí)別
  • 中止事件傳遞
  • 訂閱者索引

傳遞數(shù)據(jù)

不過(guò),上面只是發(fā)了一個(gè)空的消息,沒(méi)有傳遞任何的數(shù)據(jù),比如:我修改了用戶(hù)的頭像,上傳到服務(wù)器,服務(wù)器返回一個(gè)Url,這時(shí)候我需要修改其它界面的頭像,這時(shí)候我要把這個(gè)url數(shù)據(jù)傳到其它界面:怎么做呢?

1.只需要去修改定義事件類(lèi)中的構(gòu)造函數(shù),增加一個(gè)參數(shù),在加上set和get方法,如下:

public class UpdateHeadPicEvent {
  private String mUrl;
  public UpdateHeadPicEvent(String url) {
    this.mUrl = url;
  }
  public String getUrl() {
    return mUrl;
  }
}

2.在發(fā)送事件的地方,使用這個(gè)帶參的構(gòu)造去創(chuàng)建對(duì)象:

EventBus.getDefault().post(new UpdateHeadImgEvent(url));

3.在接收消息的回調(diào)中用get方法去獲取

@Subscribe
public void onUpdateHeadPicEvent(UpdateHeadPicEvent event) {
  String url = event.getUrl();
  Log.i(TAG, "onUpdateHeadPicEvent: " + url);
}

Note:這里只是用了一個(gè)String的Url做參考,可以傳遞的數(shù)據(jù)還有很多,List集合,Bean對(duì)象...

指定事件接收的線(xiàn)程

前面說(shuō)了加上@Subscribe注解,這個(gè)函數(shù)在消息推送之后會(huì)被回調(diào),其實(shí)這個(gè)注解還有幾個(gè)屬性,其中threadMode能為該函數(shù)指定線(xiàn)程,如果不寫(xiě),也會(huì)有個(gè)默認(rèn)值:ThreadMode.POSTING,意思是和發(fā)送事件所在線(xiàn)程一樣

@Subscribe(threadMode = ThreadMode.POSTING)
public void onUpdateHeadPicEvent(UpdateHeadPicEvent event) {
  String url = event.getUrl();
  Log.i(TAG, "onUpdateHeadPicEvent: " + url);
}

ThreadMode列表

  • ThreadMode.POSTING:和發(fā)送事件在同一個(gè)線(xiàn)程
  • ThreadMode.MAIN:主線(xiàn)程
  • ThreadMode.BACKGROUND:子線(xiàn)程
  • ThreadMode.ASYNC:異步線(xiàn)程

發(fā)送黏性事件Sticky Events

上面示例代碼所說(shuō)的情況是:當(dāng)發(fā)送消息推送者推送消息的時(shí)候,訂閱者會(huì)立馬收到消息,它會(huì)把消息推送給它所有的訂閱者.注意后面這句話(huà):如果你希望在消息推送完成之后,讓新注冊(cè)的訂閱者也能收到這條消息,這時(shí)候你可以試試Sticky Events,這個(gè)事件就像一個(gè)常駐廣播,只要是有新的訂閱者訂閱了這個(gè)事件,就會(huì)收到消息.當(dāng)然,有兩點(diǎn)要求:

  1. 首先,發(fā)送的是黏性事件,代碼將post改為postSticky
// EventBus.getDefault().post(new MessageEvent());
EventBus.getDefault().postSticky(new MessageEvent());
  1. 然后,訂閱者要聲明自己能夠接收到黏性事件的消息:代碼中@Subscribe注解中的sticky值為true,滿(mǎn)足了這兩點(diǎn),就能愉快的玩耍了.
@Override
protected void onStart() {
  super.onStart();
  if (!EventBus.getDefault().isRegistered(this)) {
  EventBus.getDefault().register(this);
  }
}

@Subscribe(sticky = true)
public void onMessageEvent(MessageEvent event) {
  Log.i(TAG, "onMessageEvent: 我是sticky event 收到消息");
}

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

測(cè)試Log日志


Paste_Image.png

接收事件的優(yōu)先級(jí)別

EventBus可以定義接收事件方的優(yōu)先級(jí)別,在@Subscribe注解中有一個(gè)priority的參數(shù),默認(rèn)值是0,可以自行配置1.2.3.4...數(shù)值越大優(yōu)先級(jí)越低,會(huì)越晚收到消息

@Subscribe(priority = 0)
public void onUpdateHeadPicEvent(UpdateHeadPicEvent event) {
  String url = event.getUrl();
  Log.i(TAG, "onUpdateHeadPicEvent: " + url);
}

中止事件傳遞

類(lèi)似于有序廣播,優(yōu)先級(jí)高的訂閱者,可以終止事件向下傳遞,EventBus也提供了此功能

@Subscribe(priority = 0)
public void onUpdateHeadPicEvent(UpdateHeadPicEvent event) {
  EventBus.getDefault().cancelEventDelivery(event) ;
}

訂閱者索引

這個(gè)新特性是在EventBus 3.0推出,簡(jiǎn)單的說(shuō):利用annotationProcessor去生成一個(gè)關(guān)于訂閱者的索引類(lèi),保存訂閱者的相關(guān)信息.
有什么用?提高效率,注冊(cè)從運(yùn)行時(shí)的反射,轉(zhuǎn)移到了編譯時(shí)
怎么用?兩種方式:

  • 在gradle版本2.2.0以前使用:Android-apt
  • 在gradle版本2.2.0以上使用:annotationProcessor

這里說(shuō)annotationProcessor的方式,現(xiàn)在新建項(xiàng)目一般都在2.2.0以上:
添加好Gradle設(shè)置之后,重新build項(xiàng)目,就會(huì)為你生成這樣的類(lèi):MyEventBusIndex
![](/assets/EventBus Annotaion Processor.png)

用法:將它配置應(yīng)用于默認(rèn)的EventBus,調(diào)用下面代碼:可放在Application的onCreate中調(diào)用

EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();

未添加前和添加后我分別做了三次測(cè)試,注冊(cè)完成的時(shí)間對(duì)比,速度快了不止一倍,這還是只有兩個(gè)訂閱者的時(shí)候,如果訂閱訂閱者更多呢,

//未添加前
I/Subscriber1Activity: onMessageEvent: register start 1491892487664
I/Subscriber1Activity: onMessageEvent: register end 1491892487666
I/Subscriber1Activity: onMessageEvent: register start 1491892568177
I/Subscriber1Activity: onMessageEvent: register end 1491892568180
I/Subscriber1Activity: onMessageEvent: register start 1491892715342
I/Subscriber1Activity: onMessageEvent: register end 1491892715344

//添加后
I/Subscriber1Activity: onMessageEvent: register start 1491892648185
I/Subscriber1Activity: onMessageEvent: register end 1491892648186
I/Subscriber1Activity: onMessageEvent: register start 1491892814517
I/Subscriber1Activity: onMessageEvent: register end 1491892814518
I/Subscriber1Activity: onMessageEvent: register start 1491892868879
I/Subscriber1Activity: onMessageEvent: register end 1491892868880
在Lib的model中使用:

build.gradle也要添加上圖中同樣的參數(shù),在上圖中,這個(gè)參數(shù)是自定義的,不同的model可以為他生成不同的索引類(lèi):

arguments = [eventBusIndex: 'com.example.myapp.MyEventBusIndex']

更改默認(rèn)配置也需要多添加一行代碼:

EventBus eventBus = EventBus.builder()
    .addIndex(new MyEventBusAppIndex())
    .addIndex(new MyEventBusLibIndex())
    .installDefaultEventBus();

最后代碼地址:https://github.com/Shib90/Eventbusdemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末斩郎,一起剝皮案震驚了整個(gè)濱河市脑融,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缩宜,老刑警劉巖肘迎,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異锻煌,居然都是意外死亡妓布,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)宋梧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)匣沼,“玉大人,你說(shuō)我怎么就攤上這事捂龄∈吞危” “怎么了加叁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)唇撬。 經(jīng)常有香客問(wèn)我它匕,道長(zhǎng),這世上最難降的妖魔是什么窖认? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任豫柬,我火速辦了婚禮,結(jié)果婚禮上耀态,老公的妹妹穿的比我還像新娘轮傍。我一直安慰自己暂雹,他們只是感情好首装,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著杭跪,像睡著了一般仙逻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涧尿,一...
    開(kāi)封第一講書(shū)人閱讀 51,610評(píng)論 1 305
  • 那天系奉,我揣著相機(jī)與錄音,去河邊找鬼姑廉。 笑死缺亮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桥言。 我是一名探鬼主播萌踱,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼号阿!你這毒婦竟也來(lái)了并鸵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤扔涧,失蹤者是張志新(化名)和其女友劉穎园担,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體枯夜,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡弯汰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了湖雹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝙泼。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖劝枣,靈堂內(nèi)的尸體忽然破棺而出汤踏,到底是詐尸還是另有隱情织鲸,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布溪胶,位于F島的核電站搂擦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏哗脖。R本人自食惡果不足惜瀑踢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望才避。 院中可真熱鬧橱夭,春花似錦、人聲如沸桑逝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)楞遏。三九已至茬暇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寡喝,已是汗流浹背糙俗。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留预鬓,地道東北人巧骚。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像格二,于是被迫代替她去往敵國(guó)和親劈彪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理蟋定,服務(wù)發(fā)現(xiàn)粉臊,斷路器,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 對(duì)于Android開(kāi)發(fā)老司機(jī)來(lái)說(shuō)肯定不會(huì)陌生驶兜,它是一個(gè)基于觀察者模式的事件發(fā)布/訂閱框架扼仲,開(kāi)發(fā)者可以通過(guò)極少的代碼...
    飛揚(yáng)小米閱讀 1,478評(píng)論 0 50
  • EventBus 是一個(gè)Android端優(yōu)化的 publish/subscribe 消息總線(xiàn),簡(jiǎn)化了應(yīng)用程序各個(gè)組...
    王世軍Steven閱讀 1,855評(píng)論 4 21
  • 前言:EventBus出來(lái)已經(jīng)有一段時(shí)間了,github上面也有很多開(kāi)源項(xiàng)目中使用了EventBus抄淑。所以抽空學(xué)習(xí)...
    Kerry202閱讀 1,286評(píng)論 1 2
  • 不是只有言語(yǔ)屠凶, 才承載著愛(ài)。 它是那么的輕盈肆资, 無(wú)聲無(wú)息矗愧, 無(wú)處不在。 是陽(yáng)光親吻萬(wàn)物的溫度郑原, 是月光投入大地的依...
    衿靈閱讀 241評(píng)論 0 0