EventBus源碼解析(六)-粘性事件發(fā)布

前言

粘性事件是指:發(fā)布者發(fā)送事件的動作發(fā)生在訂閱者訂閱該事件的動作之前,訂閱者在訂閱之后,仍然可以處理該事件。

我們在發(fā)送粘性事件時,通常是這樣寫的:

EventBus.getDefault().postSticky(event);

往下看看postSticky的邏輯。


一、主要流程

    public void postSticky(Object event) {
        synchronized (stickyEvents) {
            stickyEvents.put(event.getClass(), event);
        }

        post(event);
    }

postSticky的邏輯簡單明了,首先將事件存入stickyEvents里,然后調用普通事件的post方法,執(zhí)行與普通post相同的邏輯。

讀者看到這里,不知道會不會有疑問:

  1. 粘性事件的發(fā)布和普通事件的發(fā)布好像沒什么區(qū)別,它是怎么做到粘性的效果呢?
  2. 在register的時候,有調用了checkPostStickyEventToSubscription方法,該方法和postSticky里的post方法最終都調用了postToSubscription,這樣不就重復了嗎?

讀者請仔細觀察,在postSticky方法里,是有把事件緩存到stickyEvents中的。postSticky里的post方法,是訂閱者的訂閱事件的動作發(fā)生在粘性事件發(fā)布之前,此時粘性事件相當于普通事件,所以直接調用post處理即可。但如果訂閱者的訂閱事件的動作發(fā)生在粘性事件發(fā)布之后呢?此時就輪到stickyEvents起作用了,在注冊方法里,會取出所有未處理的緩存的粘性事件,發(fā)送到checkPostStickyEventToSubscription處理,這樣不就達到粘性事件的處理效果了嗎?

其實這種場景在實際開發(fā)中是很常見的。比如我們在某個非UI線程發(fā)布一個事件,在訂閱該事件的訂閱方法里去啟動某個Activity,此時,由于事件發(fā)布和Activity啟動不在同一個線程,且Activity啟動的速度和事件發(fā)布的速度也不可知,就有可能出現(xiàn)兩種情況(發(fā)布普通事件的場景):

  1. Activity先起來,事件后發(fā)送,此時沒有添加sticky=true的訂閱方法可以處理到該事件
  2. Activity后起來,事件先發(fā)送,此時沒有添加sticky=true的訂閱方法就處理不到該事件了

而粘性事件正好可以處理場景2的需求。


結束語

那么,有聰明的讀者就會說了:那直接把應用中的所有事件都以粘性事件發(fā)布,這樣不就可以高枕無憂了?

其實不然。首先,粘性事件是以Map緩存的,事件越多,越占內存;其次,每次注冊執(zhí)行register時,都會將所有緩存的粘性事件調用訂閱方法處理,如果處理過的粘性事件沒有清除,對于應用功能可能是有影響的。建議讀者不要圖省事而種下禍根。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,933評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,310評論 25 708
  • EventBus用法及源碼解析目錄介紹1.EventBus簡介1.1 EventBus的三要素1.2 EventB...
    楊充211閱讀 1,919評論 0 4
  • 與字卡寶寶(づ ̄ 3 ̄)づ做游戲 我是點讀機?( 'ω' )? 身體律動 小手拍拍 每日一拍
    大地一部小五班月玥老師閱讀 185評論 0 0
  • 很久以前有一次坐火車,我斜對過有三個人聊得特別火,火到什么程度?賣貨小車過來了,那個女孩非要搶著給另兩人買飲...
    apuma閱讀 272評論 0 1