【Android】事件處理之EventBus3.0解析

前言

EventBus是針對Android優(yōu)化的發(fā)布/訂閱事件總線讲竿。主要用來簡化組件間题禀、組件與后臺線程間的通信膀捷。優(yōu)點是開銷小,代碼更優(yōu)雅秀仲,以及將發(fā)送者和接收者解耦壶笼。如果Activity和Activity進行交互還好說,如果Fragment和Fragment進行交互著實令人頭疼保礼,我們會使用廣播來處理责语,但是使用廣播稍顯麻煩并且效率也不高,如果傳遞的數(shù)據(jù)是實體類需要序列化铝阐,那么很顯然成本會有點高铐拐。今天我們就來學習下EventBus3.0的使用方法遍蟋。

1.EventBus概述

EventBus的三要素

EventBus有三個主要的元素需要我們先了解一下:

  • Event:事件螟凭,可以是任意類型的對象。
  • Subscriber:事件訂閱者棒厘,在EventBus3.0之前消息處理的方法只能限定于onEvent、onEventMainThread奢人、onEventBackgroundThread和onEventAsync,他們分別代表四種線程模型句惯。而在EventBus3.0之后支救,事件處理的方法可以隨便取名,但是需要添加一個注解@Subscribe指孤,并且要指定線程模型(默認為POSTING)邓厕,四種線程模型下面會講到扁瓢。
  • Publisher:事件發(fā)布者,可以在任意線程任意位置發(fā)送事件昧互,直接調用EventBus的post(Object)方法伟桅。可以自己實例化EventBus對象玖雁,但一般使用EventBus.getDefault()就好了盖腕,根據(jù)post函數(shù)參數(shù)的類型,會自動調用訂閱相應類型事件的函數(shù)劲厌。

EventBus的四種ThreadMode(線程模型)

EventBus3.0有以下四種ThreadMode:

  • POSTING(默認):如果使用事件處理函數(shù)指定了線程模型為POSTING听隐,那么該事件在哪個線程發(fā)布出來的,事件處理函數(shù)就會在這個線程中運行风范,也就是說發(fā)布事件和接收事件在同一個線程。在線程模型為POSTING的事件處理函數(shù)中盡量避免執(zhí)行耗時操作虑润,因為它會阻塞事件的傳遞拳喻,甚至有可能會引起ANR猪腕。
  • MAIN:
    事件的處理會在UI線程中執(zhí)行。事件處理時間不能太長亚亲,長了會ANR的腐缤。
  • BACKGROUND:如果事件是在UI線程中發(fā)布出來的,那么該事件處理函數(shù)就會在新的線程中運行惜索,如果事件本來就是子線程中發(fā)布出來的剃浇,那么該事件處理函數(shù)直接在發(fā)布事件的線程中執(zhí)行。在此事件處理函數(shù)中禁止進行UI更新操作角塑。
  • ASYNC:無論事件在哪個線程發(fā)布淘讥,該事件處理函數(shù)都會在新建的子線程中執(zhí)行,同樣窒朋,此事件處理函數(shù)中禁止進行UI更新操作炼邀。

2.EventBus基本用法

EventBus使用起來很簡單剪侮,分為五個步驟:

1.自定義一個事件類

public class MessageEvent {
    ...
}

2.在需要訂閱事件的地方注冊事件

EventBus.getDefault().register(this);

3.發(fā)送事件

EventBus.getDefault().post(messageEvent);

4.處理事件

@Subscribe(threadMode = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent) {
    ...
}

前面我們說過,消息處理的方法可以隨便取名杰标,但是需要添加一個注解@Subscribe彩匕,并且要指定線程模型(默認為POSTING)。

5.取消事件訂閱

EventBus.getDefault().unregister(this);

3.EventBus3.0應用

上面講到了基本用法掸犬,有的同學可能還是有點暈湾碎,這里舉一個例子來應用EventBus3.0奠货。

添加依賴庫

Android Studio 配置gradle:

compile 'org.greenrobot:eventbus:3.0.0'

定義消息事件類

public class MessageEvent {

    private String message;

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

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

注冊和取消訂閱事件

MainActivity中注冊和取消訂閱事件(MainActivity.java):

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class MainActivity extends AppCompatActivity {
    private TextView tv_message;
    private Button bt_message;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_message=(TextView)this.findViewById(R.id.tv_message);
        tv_message.setText("MainActivity");
        bt_message=(Button)this.findViewById(R.id.bt_message);
        bt_message.setText("跳轉到第二個Activity");
        bt_message.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              startActivity(new Intent(MainActivity.this,SecondActivity.class));
            }
        });
        //注冊事件
        EventBus.getDefault().register(this);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //取消注冊事件
        EventBus.getDefault().unregister(this);
    }
 }    

事件訂閱者處理事件

這里我們的ThreadMode設置為MAIN柔滔,事件的處理會在UI線程中執(zhí)行萍虽,用TextView來展示收到的事件消息:

   @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMoonEvent(MessageEvent messageEvent){
        tv_message.setText(messageEvent.getMessage());
    }

事件發(fā)布者發(fā)布事件

這里創(chuàng)建了SecondActivity來發(fā)布消息:

public class SecondActivity extends AppCompatActivity {
    private Button bt_message;
    private TextView tv_message;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_message=(TextView)this.findViewById(R.id.tv_message);
        tv_message.setText("SecondActivity");
        bt_message=(Button)this.findViewById(R.id.bt_message);
        bt_message.setText("發(fā)送事件");
        bt_message.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().post(new MessageEvent("發(fā)送事件成功"));
                finish();
            }
        });

    }
}

4.EventBus3.0粘性事件

除了上面講的普通事件外杉编,EventBus還支持發(fā)送黏性事件,就是在發(fā)送事件之后再訂閱該事件也能收到該事件卵迂,跟黏性廣播類似绒净。為了驗證粘性事件我們修改以前的代碼:

訂閱粘性事件

在MainActivity中我們將注冊事件添加到button的點擊事件中:

  bt_subscription.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //注冊事件
                EventBus.getDefault().register(MainActivity.this);
            }
        });

訂閱者處理粘性事件

在MainActivity中新寫一個方法用來處理粘性事件:

   @Subscribe(threadMode = ThreadMode.POSTING,sticky = true)
    public void ononMoonStickyEvent(MessageEvent messageEvent){
        tv_message.setText(messageEvent.getMessage());
    }

發(fā)送黏性事件

在SecondActivity中我們定義一個Button來發(fā)送粘性事件:

   bt_subscription.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().postSticky(new MessageEvent("粘性事件"));
                finish();
            }
        });

好了運行代碼再來看看效果改览,首先我們在MainActivity中并沒有訂閱事件宝当,而是直接跳到SecondActivity中點擊發(fā)送粘性事件按鈕胆萧,這時界面回到MainActivity俐东,我們看到TextView仍舊顯示著MainActivity的字段虏辫,這是因為我們現(xiàn)在還沒有訂閱事件锈拨。

接下來我們點擊訂閱事件,TextView發(fā)生改變顯示“粘性事件”奕枢,大功告成。

EventBus3.0的使用就暫時分析到這兒稿黄,最后是混淆規(guī)則跌造。

5.ProGuard 混淆規(guī)則

-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末壳贪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子互纯,更是在濱河造成了極大的恐慌磕蒲,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兔院,死亡現(xiàn)場離奇詭異坊萝,居然都是意外死亡许起,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門惦积,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猛频,“玉大人蛛勉,你說我怎么就攤上這事董习“唬” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵恬试,是天一觀的道長训柴。 經(jīng)常有香客問我妇拯,道長,這世上最難降的妖魔是什么仗嗦? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任甘凭,我火速辦了婚禮,結果婚禮上德撬,老公的妹妹穿的比我還像新娘躲胳。我一直安慰自己,他們只是感情好蝠咆,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布北滥。 她就那樣靜靜地躺著,像睡著了一般菊霜。 火紅的嫁衣襯著肌膚如雪济赎。 梳的紋絲不亂的頭發(fā)上记某,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天液南,我揣著相機與錄音勾徽,去河邊找鬼。 笑死畅姊,一個胖子當著我的面吹牛,可吹牛的內容都是我干的若未。 我是一名探鬼主播倾鲫,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼乌昔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了甚淡?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤贯卦,失蹤者是張志新(化名)和其女友劉穎撵割,沒想到半個月后辙芍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡庶灿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年往踢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峻呕。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖瘦癌,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情热押,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布楞黄,位于F島的核電站池凄,受9級特大地震影響,放射性物質發(fā)生泄漏致盟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一馏锡、第九天 我趴在偏房一處隱蔽的房頂上張望游岳。 院中可真熱鬧列疗,春花似錦党巾、人聲如沸齿拂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽医男。三九已至,卻和暖如春刀森,著一層夾襖步出監(jiān)牢的瞬間丰辣,已是汗流浹背禽捆。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工飘哨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浊服。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓胚吁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親孽拷。 傳聞我的和親對象是個殘疾皇子半抱,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內容