Android?EventBus粘性事件實(shí)現(xiàn)機(jī)制探究
眾所周知,EventBus是支持粘性事件的,即可以先發(fā)送粘性事件,然后再注冊(cè),代碼如下:
- 粘性事件觀察者
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun registerEventBus(o: Any) {
}- 發(fā)送粘性事件
EventBus.getDefault().postSticky(Any())
- 注冊(cè)EventBus
EventBus.getDefault().register(this)
接下來(lái)我們就來(lái)探究下EventBus的粘性事件是如何實(shí)現(xiàn)的。
postSticky()內(nèi)部機(jī)制

- 如果是發(fā)送的粘性事件,會(huì)添加到
stickyEvents中,看下這個(gè)屬性的實(shí)現(xiàn):

可以看到這個(gè)屬性是一個(gè)Map集合,其中key為事件類型的class對(duì)象,value為對(duì)應(yīng)的事件類型。
- 繼續(xù)看下
post(Event)方法:

首先將這個(gè)粘性事件添加到
PostingThreadState(線程私有)的eventQueue集合中通過(guò)
isMainThread方法判斷當(dāng)前是否為主線程,最終會(huì)調(diào)用到我們熟悉的Looper.getMainLooper() == Looper.myLooper()進(jìn)行判斷循環(huán)遍歷
eventQueue隊(duì)列,不斷的取出集合元素進(jìn)行分發(fā),看下postSinleEvent()方法如何實(shí)現(xiàn):

如果
eventInheritance為true,會(huì)查找當(dāng)前發(fā)送的粘性事件類型的父類型,并返回查找到的集合接下來(lái)就會(huì)調(diào)用
postSingleEventForEventType()方法來(lái)進(jìn)行最終粘性事件的分發(fā),即通知通過(guò)@Subscribe注解注冊(cè)的粘性事件觀察者,看下具體實(shí)現(xiàn):

- 調(diào)用
subscriptionsByEventType獲取注冊(cè)該事件類型的所有訂閱方法,但是由于這個(gè)時(shí)候我們是先發(fā)送的粘性事件再注冊(cè)EventBus,而subscriptionsByEventType中集合元素的填充實(shí)在注冊(cè)EventBus發(fā)生的,所以通過(guò)subscriptionsByEventType獲取到的subscriptions將是null的,所以接下來(lái)肯定不會(huì)走下面的if代碼塊中的邏輯了。
postSticky()小結(jié)
上面這么多代碼邏輯,其實(shí)只干了一件事,就是將這個(gè)粘性事件添加到了stickyEvents這個(gè)集合中。之后的邏輯雖多,但和粘性事件沒(méi)啥關(guān)系。
register內(nèi)部機(jī)制

findSubscriberMethods()這個(gè)方法里面的邏輯就不帶大家進(jìn)行分析了,總之就干了一件事情:
查找當(dāng)前類通過(guò)
@Subscribe注冊(cè)的所有事件訂閱方法,并返回一個(gè)List<SubscriberMethod>集合,其中SubscriberMethod就是對(duì)每個(gè)注冊(cè)的訂閱方法和當(dāng)前注冊(cè)類的封裝
subscribe這個(gè)方法是關(guān)鍵,深入探究下:


第1、2、3、4步中其實(shí)就干了兩件事情:
- 填充
subscriptionsByEventType集合,key為事件類型,value為通過(guò)@Subscribe訂閱了該事件類型的方法集合 - 填充
typesBySubscriber集合,key為注冊(cè)EventBus的類,value為該類中所有@Subscribe注解修飾的方法集合
- 填充
第5步就是實(shí)現(xiàn)粘性事件分發(fā)的關(guān)鍵地方
- 首先判斷當(dāng)前
@Subscribe修飾的訂閱方法是否為粘性,即@Subscribe(sticky = true)中sticky等于true - 是的話就從
stickyEvents集合中判斷是否存在和訂閱方法中注冊(cè)的事件類型相同的事件:
這個(gè)
stickyEvents是不是很熟悉,就是我們之前發(fā)送粘性事件時(shí),將粘性事件添加到的方法集合- 如果存在,則就執(zhí)行該粘性事件的分發(fā),即調(diào)用執(zhí)行該訂閱方法,最終會(huì)調(diào)用到
invokeSubscriber()方法:
- 首先判斷當(dāng)前

從上面可以看到,最終是通過(guò)反射來(lái)實(shí)現(xiàn)的訂閱了粘性事件方法的執(zhí)行。
register小結(jié)
該方法最終會(huì)判斷當(dāng)前是否存在注冊(cè)EventBus前發(fā)送的粘性事件,且當(dāng)前注冊(cè)類中存在訂閱該事件類型的方法,然后立即執(zhí)行。
總結(jié)
以上就是EventBus粘性事件的內(nèi)部實(shí)現(xiàn)機(jī)制,總體來(lái)說(shuō)不算復(fù)雜,大家看著文章跟著源碼一步步分析應(yīng)該就很容易理解這部分實(shí)現(xiàn)邏輯了。
到此這篇關(guān)于Android EventBus粘性事件實(shí)現(xiàn)機(jī)制的文章就介紹到這了,更多相關(guān)Android EventBus粘性事件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android自定義View實(shí)現(xiàn)打鉤動(dòng)畫(huà)功能
本篇文章通過(guò)實(shí)例給大家分享了Android自定義View實(shí)現(xiàn)打鉤動(dòng)畫(huà)功能的過(guò)程和代碼分享,有興趣需要的學(xué)習(xí)下吧。2017-12-12
Android activity動(dòng)畫(huà)不生效原因及解決方案總結(jié)
android activity動(dòng)畫(huà)是一個(gè)比較簡(jiǎn)單的功能。但是使用時(shí)總會(huì)由于各種小問(wèn)題導(dǎo)致動(dòng)畫(huà)失效,筆者根據(jù)自己經(jīng)驗(yàn),整理了各種可能導(dǎo)致的原因,期望能對(duì)你有所幫助2021-11-11
淺談Android onTouchEvent 與 onInterceptTouchEvent的區(qū)別詳解
本篇文章小編為大家介紹,Android onTouchEvent 與 onInterceptTouchEvent的區(qū)別詳解。需要的朋友參考下2013-04-04
解決android 顯示內(nèi)容被底部導(dǎo)航欄遮擋的問(wèn)題
今天小編就為大家分享一篇解決android 顯示內(nèi)容被底部導(dǎo)航欄遮擋的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
探討:如何修改Android超時(shí)休眠時(shí)間
本篇文章是對(duì)如何修改Android超時(shí)休眠時(shí)間的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
Android多線程斷點(diǎn)續(xù)傳下載示例詳解
這篇文章主要為大家詳細(xì)介紹了Android多線程斷點(diǎn)續(xù)傳下載示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
Android仿小米安全中心檢測(cè)進(jìn)度條效果
這篇文章主要介紹了Android仿小米安全中心檢測(cè)進(jìn)度條效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
Android 中的危險(xiǎn)權(quán)限詳細(xì)整理
這篇文章主要介紹了Android 中的危險(xiǎn)權(quán)限詳細(xì)整理的相關(guān)資料,Android 中有上百種權(quán)限,現(xiàn)在將所有的權(quán)限歸為兩類,一類是普通權(quán)限,一類的危險(xiǎn)權(quán)限,危險(xiǎn)權(quán)限則表示那些可能會(huì)觸及到用戶安全隱私或者對(duì)設(shè)備安全造成影響的權(quán)限,需要的朋友可以參考下2017-07-07
android利用handler實(shí)現(xiàn)打地鼠游戲
這篇文章主要為大家詳細(xì)介紹了android利用handler實(shí)現(xiàn)打地鼠游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11

