02-EventBus玩轉(zhuǎn)消息傳遞

EventBus3.0以后使用了注解模式,接收消息的方法名可以讓你任性的寫寫寫状您,不再是以onEvent開頭了勒叠,增加了可讀性兜挨,用著更爽了。那么我們?cè)诎岽u的時(shí)候怎么去愉快的使用呢眯分?

磚家認(rèn)為可以在Activity與Activity拌汇、Activity與Fragment、線程之間愉快的傳遞數(shù)據(jù)弊决,還可以替代intent傳值噪舀,還不用去寫序列化,臥槽飘诗,爽炸天有木有与倡。

官網(wǎng)地址:
EventBus GitHub地址
在Android Studio中添加如下依賴即可使用:

compile 'org.greenrobot:eventbus:3.0.0'

one step :下面介紹下使用方法

1、首先需要寫好注冊(cè)與注銷方法:

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main)疚察;
        //注冊(cè)EventBus
        EventBus.getDefault().register(this);
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //注銷EventBus
        EventBus.getDefault().unregister(this);
    }

2、碼好接收消息的方法:

自定義消息實(shí)體EventMessage,data使用泛型仇奶,可以接收任意類型的數(shù)據(jù)

public class EventMessage<T> {
    private int type;
    private T data;

    public EventMessage(int type, T data) {
        this.type = type;
        this.data = data;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
 /**
     * 接收消息
     * @param msg
     */
    @Subscribe(sticky = true,threadMode = ThreadMode.MAIN)
    public void eventComing(EventMessage<String> msg){
        if(msg.getType() == 2){
            tv_content.setText(msg.getData());
        }
    }

sticky 設(shè)置是否接收粘性消息貌嫡,threadMode 設(shè)置運(yùn)行的線程,還有一個(gè)priority設(shè)置接收消息的優(yōu)先級(jí)
根據(jù)type的值去區(qū)分不同的發(fā)送和接收该溯。

3岛抄、發(fā)送消息:

發(fā)送消息可以分兩種:
一、粘性消息

 @Subscribe(sticky = true,threadMode = ThreadMode.MAIN)

sticky 為true的時(shí)候就是粘性消息狈茉,什么是粘性消息呢夫椭?就是EventBus可以先出消息體,然后在EventBus進(jìn)行注冊(cè)的時(shí)候從粘性消息隊(duì)列中取出消息氯庆,進(jìn)行接收,可用于替代intent傳值蹭秋。
發(fā)送方法使用:

EventBus.getDefault().postSticky(new EventMessage<String>(1,"來(lái)自第一世界的消息"));

注意:如果需要接收粘性消息后操作界面,那么threadMode = ThreadMode.MAIN設(shè)為主線程堤撵,而且EventBus注冊(cè)必須在界面初始化之后進(jìn)行仁讨,因?yàn)檎承韵⒃贓ventBus注冊(cè)的時(shí)候被接收。

二实昨、普通消息
普通消息洞豁,只能先注冊(cè)后接收。發(fā)出的消息荒给,只能注冊(cè)過(guò)的EventBus進(jìn)行接收丈挟。用于替代Handler+Message
使用方法:

EventBus.getDefault().post(new EventMessage<String>(2,"來(lái)自第二世界的消息"));

two step :下面介紹EventBus的原理。

源碼大家可以根據(jù)原理自己觀摩學(xué)習(xí)志电,對(duì)于磚家曙咽,你可以直接搬磚使用,但學(xué)習(xí)源碼挑辆,能讓你更懂得如何搬磚桐绒。各人自由發(fā)揮吧夺脾。
1、想成為訂閱者茉继,需要進(jìn)行注冊(cè)

EventBus.getDefault().register(this);

那么先從getDefault()方法走起咧叭,定睛一看,so easy,老司機(jī)都懂烁竭,不解釋菲茬。

public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}

獲取實(shí)例直接調(diào)用了EventBus構(gòu)造方法

   public EventBus() {
        this(DEFAULT_BUILDER);
    }

    private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
    private final Map<Object, List<Class<?>>> typesBySubscriber;
    private final Map<Class<?>, Object> stickyEvents;

    private final HandlerPoster mainThreadPoster;
    private final BackgroundPoster backgroundPoster;
    private final AsyncPoster asyncPoster;
    EventBus(EventBusBuilder builder) {
        //key為訂閱事件  value為訂閱這個(gè)事件的所有訂閱者的CopyOnWriteArrayList
        subscriptionsByEventType = new HashMap<>();
       //以訂閱者的類為key,以event事件類為value派撕,在進(jìn)行register或unregister的時(shí)候婉弹,會(huì)操作這HashMap。
        typesBySubscriber = new HashMap<>();
        //粘性事件的集合
        stickyEvents = new ConcurrentHashMap<>();
        //事件處理
        mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
        backgroundPoster = new BackgroundPoster(this);
        asyncPoster = new AsyncPoster(this);
        ......
    }

register()方法:

   public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods =       subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

注冊(cè)的時(shí)候通過(guò)subscriberMethodFinder的findSubscriberMethods方法去查找和緩存訂閱者訂閱了哪些事件.返回一個(gè)SubscriberMethod(SubscriberMethod里包含了這個(gè)方法的Method對(duì)象,以及將來(lái)響應(yīng)訂閱是在哪個(gè)線程的ThreadMode,以及訂閱的事件類型eventType,以及訂閱的優(yōu)先級(jí)priority,以及是否接收粘性sticky事件的boolean值)對(duì)象的List终吼。

接著回到subscribe(subscriber, subscriberMethod)中去,通過(guò)這個(gè)方法,我們就完成了注冊(cè)镀赌。具體代碼自行去觀摩吧。


2际跪、事件的發(fā)送Post

/** Posts the given event to the event bus. */
    public void post(Object event) {
        //獲取當(dāng)前線程信息
        //currentPostingThreadState是一個(gè)ThreadLocal
        //ThreadLocal 是一個(gè)線程內(nèi)部的數(shù)據(jù)存儲(chǔ)類商佛,通過(guò)它可以在指定的線程中存儲(chǔ)數(shù)據(jù),
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        //把事件加入線程隊(duì)列中
        eventQueue.add(event);
        if (!postingState.isPosting) {
            postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
            postingState.isPosting = true;
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                while (!eventQueue.isEmpty()) {
                    //不斷從隊(duì)列中獲取發(fā)送單個(gè)事件
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

大致原理是通過(guò)ThreadLocal存儲(chǔ)指定線程的數(shù)據(jù)姆打,數(shù)據(jù)在當(dāng)前線程中的事件隊(duì)列中不停往外分發(fā)良姆。


磚家說(shuō)句話

EventBus先介紹到這,還有很多細(xì)節(jié)沒(méi)有深入幔戏,大家各自去看吧玛追。我們搬磚的時(shí)候首先得學(xué)會(huì)使用,解決工作中的問(wèn)題闲延,然后有空再去觀摩下源碼痊剖,學(xué)習(xí)學(xué)習(xí)。要想看懂這個(gè)源碼垒玲,要會(huì)數(shù)據(jù)結(jié)構(gòu)邢笙、設(shè)計(jì)模式、java注解與反射等侍匙。所以啊氮惯,基礎(chǔ)要牢靠,滴滴滴想暗,走起吧8竞埂!说莫!

demo下載地址:
http://pan.baidu.com/s/1i5DUcML

要想看源碼杨箭,也可參考如下文章,寫的不錯(cuò):
http://www.reibang.com/p/f057c460c77e

http://www.reibang.com/p/bda4ed3017ba

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末储狭,一起剝皮案震驚了整個(gè)濱河市互婿,隨后出現(xiàn)的幾起案子捣郊,更是在濱河造成了極大的恐慌,老刑警劉巖慈参,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呛牲,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡驮配,警方通過(guò)查閱死者的電腦和手機(jī)娘扩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)壮锻,“玉大人琐旁,你說(shuō)我怎么就攤上這事〔滦澹” “怎么了灰殴?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)掰邢。 經(jīng)常有香客問(wèn)我牺陶,道長(zhǎng),這世上最難降的妖魔是什么尸变? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任义图,我火速辦了婚禮减俏,結(jié)果婚禮上召烂,老公的妹妹穿的比我還像新娘。我一直安慰自己娃承,他們只是感情好奏夫,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著历筝,像睡著了一般酗昼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上梳猪,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天麻削,我揣著相機(jī)與錄音,去河邊找鬼春弥。 笑死呛哟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的匿沛。 我是一名探鬼主播扫责,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼逃呼!你這毒婦竟也來(lái)了鳖孤?” 一聲冷哼從身側(cè)響起者娱,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎苏揣,沒(méi)想到半個(gè)月后黄鳍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腿准,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年际起,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吐葱。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡街望,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出弟跑,到底是詐尸還是另有隱情灾前,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布孟辑,位于F島的核電站哎甲,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏饲嗽。R本人自食惡果不足惜炭玫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望貌虾。 院中可真熱鬧吞加,春花似錦、人聲如沸尽狠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)袄膏。三九已至践图,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沉馆,已是汗流浹背码党。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留斥黑,地道東北人揖盘。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像心赶,于是被迫代替她去往敵國(guó)和親扣讼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

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

  • EventBus 是一個(gè)Android端優(yōu)化的 publish/subscribe 消息總線,簡(jiǎn)化了應(yīng)用程序各個(gè)組...
    王世軍Steven閱讀 1,846評(píng)論 4 21
  • 原文鏈接:http://blog.csdn.net/u012810020/article/details/7005...
    tinyjoy閱讀 544評(píng)論 1 5
  • 前言:EventBus出來(lái)已經(jīng)有一段時(shí)間了缨叫,github上面也有很多開源項(xiàng)目中使用了EventBus椭符。所以抽空學(xué)習(xí)...
    Kerry202閱讀 1,282評(píng)論 1 2
  • 遇見(jiàn)销钝,不難有咨,擦肩而過(guò)。 難得是相守蒸健。 人世間座享,因果輪回。 誰(shuí)又知道明天似忧,你我又在何處呢渣叛? 我喜愛(ài)蓮花,或許是因?yàn)樗?..
    慕初Sara閱讀 669評(píng)論 3 2
  • 曾經(jīng)小時(shí)候聽(tīng)到“萬(wàn)元戶”覺(jué)得多么了不起箫攀,長(zhǎng)大了想著“百萬(wàn)富翁”該是多么有錢,到現(xiàn)在幼衰,年薪百萬(wàn)靴跛,也許你還覺(jué)得活得不舒...
    首席米蟲閱讀 2,782評(píng)論 4 25