EventBus 3.x源碼解析

register(注冊(cè))

SubscriberMethod

eventbus注冊(cè)的時(shí)候回遍歷查詢已經(jīng)被Subscribe注解的方法(Method)

SubscriberMethod

包含:

  • method:包含了這個(gè)方法的全部信息,通過(guò)這個(gè)屬性,可以反射出該方法摔桦,進(jìn)行調(diào)用轴猎;
  • threadMode:該方法在什么什么線程下調(diào)用光督;
  • eventType: 事件的類(lèi)型雕憔,會(huì)通過(guò)該類(lèi)型自動(dòng)往該種類(lèi)型的eventType上追加任務(wù)酬蹋。

1萧吠、尋找List<SubscriberMethod>

2左冬、將上面找到的List<SubscriberMethod>依次進(jìn)行注冊(cè)

synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }

這樣,會(huì)形成:

subscriptionsByEventType

如上圖的數(shù)據(jù)結(jié)構(gòu)怎憋,這樣就很明確了又碌,一個(gè)EventType對(duì)應(yīng)其中所有的對(duì)其注冊(cè)的Subscription,而Subscription形如:

Subscription

這樣就很清晰了:

Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType這個(gè)map中绊袋,我們存儲(chǔ)了在何種EventType上面注冊(cè)的各種不同注冊(cè)者Subscription上面的不同的方法SubscriberMethod毕匀。

2.1、我們可以想象:
  • subscriptionsByEventType因該是至少使用HashMap作為基本的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)的癌别;
  • CopyOnWriteArrayList<Subscription>也需要做判斷重復(fù)的工作皂岔,因?yàn)椋翰恍枰胖脙杀橥粚?duì)象中各種被@Subscribe注解的方法。

所以:
如果你在同一個(gè)類(lèi)中重復(fù)調(diào)用register方法進(jìn)行注冊(cè)展姐,
譬如:

EventBus.getDefault().register(this);
EventBus.getDefault().register(this);

會(huì)拋出異常躁垛,這是顯然的。

重復(fù)register
2.2圾笨、如何進(jìn)行注冊(cè)的

3教馆、發(fā)送事件(post)

注意可能會(huì)在多線程中進(jìn)行EventBus的使用,并進(jìn)行時(shí)間的register和post擂达,eventBus有必要進(jìn)行多線程方面的考慮土铺。

使用ThreadLocal初始化并存儲(chǔ)該線程需要進(jìn)行發(fā)送的事件的容器。

關(guān)于ThreadLocal的相關(guān)知識(shí),可以參考:http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83]%E8%A7%A3%E5%AF%86ThreadLocal/

/** For ThreadLocal, much faster to set (and get multiple values). */
final static class PostingThreadState {
    final List<Object> eventQueue = new ArrayList<Object>();
    boolean isPosting;
    boolean isMainThread;
    Subscription subscription;
    Object event;
    boolean canceled;
}
3.1悲敷、發(fā)送線程相關(guān)狀態(tài)的設(shè)置
3.2究恤、 postSingleEvent
postSingleEvent(eventQueue.remove(0), postingState);

這段代碼出現(xiàn)一個(gè)疑問(wèn):postingState中已經(jīng)持有了eventQueue,為何仍舊需要這樣調(diào)用?

3.2.1后德、eventInheritance

EventBus支持發(fā)送的EventClass是否是可以繼承的,應(yīng)用場(chǎng)景就是:

為了代碼的架構(gòu)清晰部宿,某些想用的事件不需要傳遞不同的參數(shù),而只需要將各種不同的參數(shù)類(lèi)都繼承于同一個(gè)BaseClass或者實(shí)現(xiàn)同一個(gè)BaseInterface瓢湃。

譬如:小明和小紅是兄妹理张,兩人在學(xué)校里獲得了********同樣的********獎(jiǎng)項(xiàng)(這里比喻需要發(fā)送相同的事件),現(xiàn)在學(xué)校要把獎(jiǎng)狀發(fā)給小明和小紅箱季,當(dāng)然涯穷,最為直接的就是學(xué)校分別把兩張獎(jiǎng)狀給小明和小紅棍掐,但是藏雏,也可以這樣:********學(xué)校把獎(jiǎng)狀給了小明和小紅的媽媽?zhuān)蓩寢屩苯咏唤o兄妹兩人********。這里可以想象到:小明和小紅都“********繼承********”于媽媽作煌。

eventInheritance

這樣掘殴,單個(gè)事件就開(kāi)始發(fā)送了。

3.3粟誓、執(zhí)行

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            case POSTING:
                invokeSubscriber(subscription, event);
                break;
            case MAIN:
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
     // 在子線程處理需要在UI Thread處理的消息
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case BACKGROUND:
                if (isMainThread) {
                 // 在UI Thread處理需要在子線程處理的消息
                    backgroundPoster.enqueue(subscription, event);
                } else {
                    invokeSubscriber(subscription, event);
                }
                break;
            case ASYNC:
                asyncPoster.enqueue(subscription, event);
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }
3.3.1奏寨、在子線程處理需要在UI Thread處理的消息

其實(shí)就是使用Handler,發(fā)送消息到Main Looper中進(jìn)行輪詢鹰服。

mainThreadPoster.enqueue(subscription, event);
其一病瞳、PendingPost
PendingPost

這是一個(gè)用于構(gòu)造具體的方法的實(shí)體,用于傳遞給Loop是main的Handler進(jìn)行消息的處理悲酷。

值得一提的是:這是一個(gè)需要進(jìn)行反復(fù)構(gòu)造的實(shí)體套菜,反復(fù)的進(jìn)行new構(gòu)造會(huì)影響性能,所以構(gòu)造了一個(gè)pendingPostPool進(jìn)行緩存设易。這個(gè)pool的最大的容量是10000逗柴。

synchronized (pendingPostPool) {
            // Don't let the pool grow indefinitely
            if (pendingPostPool.size() < 10000) {
                pendingPostPool.add(pendingPost);
            }
        }
其二、maxMillisInsideHandleMessage

在構(gòu)造在UI Thread進(jìn)行發(fā)送信息的HandlerPoster的時(shí)候顿肺,會(huì)傳遞一個(gè)maxMillisInsideHandleMessage戏溺,但是,在想:都是同步方法屠尊,計(jì)算耗時(shí)的意義何在翱趸觥?

http://stackoverflow.com/questions/39943133/what-is-maxmillisinsidehandlemessages-meaning-here-could-someone-help-to-answ

3.3.2讼昆、在UI Thread處理需要在子線程處理的消息

這種比較容易托享,使用線程池執(zhí)行就行了。

eventBus.getExecutorService().execute(this);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绍申,一起剝皮案震驚了整個(gè)濱河市浴骂,隨后出現(xiàn)的幾起案子佃乘,更是在濱河造成了極大的恐慌解滓,老刑警劉巖乡翅,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岭妖,死亡現(xiàn)場(chǎng)離奇詭異佩抹,居然都是意外死亡酪碘,警方通過(guò)查閱死者的電腦和手機(jī)炕矮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)么夫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人肤视,你說(shuō)我怎么就攤上這事档痪。” “怎么了邢滑?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵腐螟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我困后,道長(zhǎng)乐纸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任摇予,我火速辦了婚禮汽绢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘侧戴。我一直安慰自己宁昭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布酗宋。 她就那樣靜靜地躺著积仗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪本缠。 梳的紋絲不亂的頭發(fā)上斥扛,一...
    開(kāi)封第一講書(shū)人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音丹锹,去河邊找鬼稀颁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛楣黍,可吹牛的內(nèi)容都是我干的匾灶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼租漂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼阶女!你這毒婦竟也來(lái)了颊糜?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤秃踩,失蹤者是張志新(化名)和其女友劉穎衬鱼,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體憔杨,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸟赫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了消别。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抛蚤。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖寻狂,靈堂內(nèi)的尸體忽然破棺而出岁经,到底是詐尸還是另有隱情,我是刑警寧澤蛇券,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布缀壤,位于F島的核電站,受9級(jí)特大地震影響怀读,放射性物質(zhì)發(fā)生泄漏诉位。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一菜枷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧叁丧,春花似錦啤誊、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至稚瘾,卻和暖如春牡昆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背摊欠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工丢烘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人些椒。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓播瞳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親免糕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赢乓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

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