Android框架之路——EventBus的使用


一、簡介

EventBus是由greenrobot 組織貢獻(xiàn)的一個(gè)Android事件發(fā)布/訂閱輕量級框架皆刺。EventBus是一個(gè)Android端優(yōu)化的publish/subscribe消息總線,簡化了應(yīng)用程序內(nèi)各組件間凌摄、組件與后臺線程間的通信羡蛾。比如請求網(wǎng)絡(luò),等網(wǎng)絡(luò)返回時(shí)通過Handler或Broadcast通知UI锨亏,兩個(gè)Fragment之間需要通過Listener通信痴怨,這些需求都可以通過EventBus實(shí)現(xiàn)忙干。

官網(wǎng)地址:http://greenrobot.org/eventbus/
翻譯:http://blog.csdn.net/poorkick/article/details/55099311
<p>

</p>

二、添加依賴

compile 'org.greenrobot:eventbus:3.0.0'

三浪藻、解鎖技能

  1. EventBus的三要素

    • Event:事件捐迫,可以是任意類型的對象。
    • Subscriber:事件訂閱者珠移,在EventBus3.0之前消息處理的方法只能限定于onEvent弓乙、onEventMainThread、onEventBackgroundThread和onEventAsync钧惧,他們分別代表四種線程模型暇韧。而在EventBus3.0之后,事件處理的方法可以隨便取名浓瞪,但是需要添加一個(gè)注解@Subscribe懈玻,并且要指定線程模型(默認(rèn)為POSTING)。
    • Publisher:事件發(fā)布者乾颁,可以在任意線程任意位置發(fā)送事件涂乌,直接調(diào)用EventBus的post(Object)方法∮⒘耄可以自己實(shí)例化EventBus對象湾盒,但一般使用EventBus.getDefault()就好了,根據(jù)post函數(shù)參數(shù)的類型诅妹,會自動調(diào)用訂閱相應(yīng)類型事件的函數(shù)罚勾。
  2. EventBus的四種線程模型(ThreadMode)

    • POSTING(默認(rèn)):如果使用事件處理函數(shù)指定了線程模型為POSTING,那么該事件在哪個(gè)線程發(fā)布出來的吭狡,事件處理函數(shù)就會在這個(gè)線程中運(yùn)行尖殃,也就是說發(fā)布事件和接收事件在同一個(gè)線程。在線程模型為POSTING的事件處理函數(shù)中盡量避免執(zhí)行耗時(shí)操作划煮,因?yàn)樗鼤枞录膫鬟f送丰,甚至有可能會引起應(yīng)用程序無響應(yīng)(ANR)。
    • MAIN:事件的處理會在UI線程中執(zhí)行弛秋。事件處理時(shí)間不能太長器躏,長了會ANR的。
    • BACKGROUND:如果事件是在UI線程中發(fā)布出來的蟹略,那么該事件處理函數(shù)就會在新的線程中運(yùn)行登失,如果事件本來就是子線程中發(fā)布出來的,那么該事件處理函數(shù)直接在發(fā)布事件的線程中執(zhí)行科乎。在此事件處理函數(shù)中禁止進(jìn)行UI更新操作壁畸。
    • ASYNC:無論事件在哪個(gè)線程發(fā)布,該事件處理函數(shù)都會在新建的子線程中執(zhí)行,同樣捏萍,此事件處理函數(shù)中禁止進(jìn)行UI更新操作太抓。
  3. 使用步驟

    • 注冊:EventBus.getDefault().register(this);

    • 解注冊(為防止內(nèi)存泄漏):EventBus.getDefault().unregister(this);

    • 構(gòu)造發(fā)送消息類

        public class MessageEvent {
            public String name;
            public String password;
        
            public MessageEvent(String name, String password) {
                this.name = name;
                this.password = password;
            }
        }
      
    • 發(fā)布消息:EventBus.getDefault().post(new MessageEvent("name","password"));

    • 接收消息:可以有四種線程模型選擇

        @Subscribe(threadMode = ThreadMode.MAIN)
        public void messageEventBus(MessageEvent event){
            tv_result.setText("name:"+event.name+" passwrod:"+event.password);
        }
      
  4. 粘性事件
    ???之前說的使用方法,都是需要先注冊(register)令杈,再post,才能接受到事件走敌;如果你使用postSticky發(fā)送事件,那么可以不需要先注冊逗噩,也能接受到事件掉丽,也就是一個(gè)延遲注冊的過程。
    ???普通的事件我們通過post發(fā)送給EventBus异雁,發(fā)送過后之后當(dāng)前已經(jīng)訂閱過的方法可以收到捶障。但是如果有些事件需要所有訂閱了該事件的方法都能執(zhí)行呢?例如一個(gè)Activity纲刀,要求它管理的所有Fragment都能執(zhí)行某一個(gè)事件项炼,但是當(dāng)前我只初始化了3個(gè)Fragment,如果這時(shí)候通過post發(fā)送了事件示绊,那么當(dāng)前的3個(gè)Fragment當(dāng)然能收到锭部。但是這個(gè)時(shí)候又初始化了2個(gè)Fragment,那么我必須重新發(fā)送事件面褐,這兩個(gè)Fragment才能執(zhí)行到訂閱方法拌禾。
    ???粘性事件就是為了解決這個(gè)問題,通過 postSticky 發(fā)送粘性事件展哭,這個(gè)事件不會只被消費(fèi)一次就消失湃窍,而是一直存在系統(tǒng)中,知道被 removeStickyEvent 刪除掉摄杂。那么只要訂閱了該粘性事件的所有方法坝咐,只要被register 的時(shí)候循榆,就會被檢測到析恢,并且執(zhí)行。訂閱的方法需要添加 sticky = true 屬性秧饮。

    • 構(gòu)造發(fā)送信息類

        public class StickyEvent {
            public String msg;
        
            public StickyEvent(String msg) {
                this.msg = msg;
            }
        }
      
    • 發(fā)布消息:EventBus.getDefault().postSticky(new StickyEvent("我是粘性事件"));

    • 接收消息:和之前的方法一樣映挂,只是多了一個(gè) sticky = true 的屬性。

        @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
        public void onEvent(StickyEvent event){
            tv_c_result.setText(event.msg);
        }
      
    • 注冊

        EventBus.getDefault().register(CActivity.this);
      
    • 解注冊

        EventBus.getDefault().removeAllStickyEvents();
        EventBus.getDefault().unregister(CActivity.class);
      

四盗尸、舉個(gè)栗子

  1. 主線程發(fā)送事件:

    • 自定義事件(類似定義JavaBean)柑船,包含用戶的姓名和密碼;

        public class UserEvent {
            private String name;
            private String password;
        
            public UserEvent() {
            }
        
            public UserEvent(String name, String password) {
                this.name = name;
                this.password = password;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public String getPassword() {
                return password;
            }
        
            public void setPassword(String password) {
                this.password = password;
            }
        
            @Override
            public String toString() {
                return "UserEvent{" +
                        "name='" + name + '\'' +
                        ", password='" + password + '\'' +
                        '}';
            }
        }
      
    • 在onCreate方法中注冊訂閱者泼各,在onDestroy中解注冊鞍时。

        public class MainActivity extends AppCompatActivity {
        
            @BindView(R.id.jump)
            Button mJump;
            @BindView(R.id.send)
            Button mSend;
            @BindView(R.id.tv_result)
            TextView mTvResult;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                ButterKnife.bind(this);
                //注冊訂閱者
                EventBus.getDefault().register(this);
            }
        
            @OnClick({R.id.jump, R.id.send})
            public void onViewClicked(View view) {
                switch (view.getId()) {
                    case R.id.jump:
                        startActivity(new Intent(MainActivity.this, SecActivity.class));
                        break;
                    case R.id.send:
                        break;
                }
            }
        
            //定義處理接收的方法
            @Subscribe(threadMode = ThreadMode.MAIN)
            public void userEventBus(UserEvent userEvent){
                mTvResult.setText(userEvent.toString());
            }
        
            @Override
            protected void onDestroy() {
                super.onDestroy();
                //注銷注冊
                EventBus.getDefault().unregister(this);
            }
        }
      
    • 在另一個(gè)activity中發(fā)送事件,讓訂閱者能夠接收;

        @OnClick({R.id.sendData, R.id.receive})
        public void onViewClicked(View view) {
            switch (view.getId()) {
                case R.id.sendData:
                    //發(fā)送事件
                    EventBus.getDefault().post(new UserEvent("Mr.sorrow", "123456"));
                    finish();
                    break;
                case R.id.receive:
                    break;
            }
        }
      
    • 實(shí)現(xiàn)結(jié)果:

      <p>
      </p>
  2. 發(fā)送粘性事件:

    • MainActivity中發(fā)送粘性事件逆巍;

        case R.id.send:
                EventBus.getDefault().postSticky(new MessageEvent("粘性事件", "urgent"));
                startActivity(new Intent(MainActivity.this, SecActivity.class));
                break;
      
    • SecActivity中接受注冊并處理及塘;

        public class SecActivity extends AppCompatActivity {
            @BindView(R.id.sendData)
            Button mSendData;
            @BindView(R.id.receive)
            Button mReceive;
            @BindView(R.id.tv_receive)
            TextView mTvReceive;
        
            @Override
            protected void onCreate(@Nullable Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_sec);
                ButterKnife.bind(this);
            }
        
            @OnClick({R.id.sendData, R.id.receive})
            public void onViewClicked(View view) {
                switch (view.getId()) {
                    case R.id.sendData:
                        //發(fā)送事件
                        EventBus.getDefault().post(new UserEvent("Mr.sorrow", "123456"));
                        finish();
                        break;
                    case R.id.receive:
                        //要接收時(shí)開始注冊
                        EventBus.getDefault().register(SecActivity.this);
                        break;
                }
            }
        
            //處理事件邏輯
            @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
            public void receiveEventBus(MessageEvent messageEvent) {
                mTvReceive.setText(messageEvent.toString());
            }
        
            @Override
            protected void onDestroy() {
                super.onDestroy();
                //解注冊
                EventBus.getDefault().removeAllStickyEvents();
                EventBus.getDefault().unregister(SecActivity.this);
            }
        }
      
    • 實(shí)現(xiàn)效果

      <p>
      </p>

五、栗子下載

??????源碼鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锐极,一起剝皮案震驚了整個(gè)濱河市笙僚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灵再,老刑警劉巖肋层,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異翎迁,居然都是意外死亡栋猖,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門汪榔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掂铐,“玉大人,你說我怎么就攤上這事揍异∪桑” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵衷掷,是天一觀的道長辱姨。 經(jīng)常有香客問我,道長戚嗅,這世上最難降的妖魔是什么雨涛? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮懦胞,結(jié)果婚禮上替久,老公的妹妹穿的比我還像新娘。我一直安慰自己躏尉,他們只是感情好蚯根,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著胀糜,像睡著了一般颅拦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上教藻,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天距帅,我揣著相機(jī)與錄音,去河邊找鬼括堤。 笑死碌秸,一個(gè)胖子當(dāng)著我的面吹牛绍移,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播讥电,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼登夫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了允趟?” 一聲冷哼從身側(cè)響起恼策,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎潮剪,沒想到半個(gè)月后涣楷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抗碰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年狮斗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弧蝇。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碳褒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出看疗,到底是詐尸還是另有隱情沙峻,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布两芳,位于F島的核電站摔寨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏怖辆。R本人自食惡果不足惜是复,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望竖螃。 院中可真熱鬧淑廊,春花似錦、人聲如沸特咆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坚弱。三九已至蜀备,卻和暖如春关摇,著一層夾襖步出監(jiān)牢的瞬間荒叶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工输虱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留些楣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像愁茁,于是被迫代替她去往敵國和親蚕钦。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理鹅很,服務(wù)發(fā)現(xiàn)嘶居,斷路器,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 前言:EventBus出來已經(jīng)有一段時(shí)間了促煮,github上面也有很多開源項(xiàng)目中使用了EventBus邮屁。所以抽空學(xué)習(xí)...
    Kerry202閱讀 1,282評論 1 2
  • EventBus 是一個(gè)Android端優(yōu)化的 publish/subscribe 消息總線,簡化了應(yīng)用程序各個(gè)組...
    王世軍Steven閱讀 1,845評論 4 21
  • EventBus可以實(shí)現(xiàn)組件間通信,線程通信菠齿,比較方便靈活,2.x和3.0差別很多佑吝。 Android Studio...
    Sunyard_QiL閱讀 788評論 0 2
  • 此去湘西,路過景區(qū)的大街绳匀,隱隱也聽得商鋪里傳出這首歌芋忿, 不再是宋姐的歌喉,是多數(shù)人唱腔的組合疾棵,極富地方特色戈钢。繼而,...
    滄海信風(fēng)閱讀 911評論 0 1