網站首頁 編程語言 正文
眾所周知,EventBus是支持粘性事件的,即可以先發送粘性事件,然后再注冊,代碼如下:
- 粘性事件觀察者
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true) fun registerEventBus(o: Any) { }
- 發送粘性事件
EventBus.getDefault().postSticky(Any())
- 注冊EventBus
EventBus.getDefault().register(this)
接下來我們就來探究下EventBus的粘性事件是如何實現的。
postSticky()內部機制
- 如果是發送的粘性事件,會添加到
stickyEvents
中,看下這個屬性的實現:
可以看到這個屬性是一個Map集合,其中key為事件類型的class對象,value為對應的事件類型。
- 繼續看下
post(Event)
方法:
首先將這個粘性事件添加到
PostingThreadState
(線程私有)的eventQueue
集合中通過
isMainThread
方法判斷當前是否為主線程,最終會調用到我們熟悉的Looper.getMainLooper() == Looper.myLooper()
進行判斷循環遍歷
eventQueue
隊列,不斷的取出集合元素進行分發,看下postSinleEvent()
方法如何實現:
如果
eventInheritance
為true,會查找當前發送的粘性事件類型的父類型,并返回查找到的集合接下來就會調用
postSingleEventForEventType()
方法來進行最終粘性事件的分發,即通知通過@Subscribe
注解注冊的粘性事件觀察者,看下具體實現:
- 調用
subscriptionsByEventType
獲取注冊該事件類型的所有訂閱方法,但是由于這個時候我們是先發送的粘性事件再注冊EventBus
,而subscriptionsByEventType
中集合元素的填充實在注冊EventBus
發生的,所以通過subscriptionsByEventType
獲取到的subscriptions
將是null的,所以接下來肯定不會走下面的if代碼塊中的邏輯了。
postSticky()小結
上面這么多代碼邏輯,其實只干了一件事,就是將這個粘性事件添加到了stickyEvents
這個集合中。之后的邏輯雖多,但和粘性事件沒啥關系。
register內部機制
-
findSubscriberMethods()
這個方法里面的邏輯就不帶大家進行分析了,總之就干了一件事情:
查找當前類通過
@Subscribe
注冊的所有事件訂閱方法,并返回一個List<SubscriberMethod>
集合,其中SubscriberMethod
就是對每個注冊的訂閱方法和當前注冊類的封裝
-
subscribe
這個方法是關鍵,深入探究下:
-
第1、2、3、4步中其實就干了兩件事情:
- 填充
subscriptionsByEventType
集合,key為事件類型,value為通過@Subscribe
訂閱了該事件類型的方法集合 - 填充
typesBySubscriber
集合,key為注冊EventBus的類,value為該類中所有@Subscribe
注解修飾的方法集合
- 填充
-
第5步就是實現粘性事件分發的關鍵地方
- 首先判斷當前
@Subscribe
修飾的訂閱方法是否為粘性,即@Subscribe(sticky = true)
中sticky
等于true - 是的話就從
stickyEvents
集合中判斷是否存在和訂閱方法中注冊的事件類型相同的事件:
這個
stickyEvents
是不是很熟悉,就是我們之前發送粘性事件時,將粘性事件添加到的方法集合- 如果存在,則就執行該粘性事件的分發,即調用執行該訂閱方法,最終會調用到
invokeSubscriber()
方法:
- 首先判斷當前
從上面可以看到,最終是通過反射來實現的訂閱了粘性事件方法的執行。
register小結
該方法最終會判斷當前是否存在注冊EventBus
前發送的粘性事件,且當前注冊類中存在訂閱該事件類型的方法,然后立即執行。
總結
以上就是EventBus
粘性事件的內部實現機制,總體來說不算復雜,大家看著文章跟著源碼一步步分析應該就很容易理解這部分實現邏輯了。
原文鏈接:https://juejin.cn/post/7102815596621856799
相關推薦
- 2023-02-10 Pytorch模型微調fine-tune詳解_python
- 2022-05-04 R語言數據類型與相應運算的實現_R語言
- 2023-12-22 uni-app微信小程序分包
- 2023-05-13 關于oracle數據庫表空間擴容的問題_oracle
- 2021-11-02 Linux環境下生成openssl證書注意細節介紹_Linux
- 2022-07-03 Android實現翻頁特效_Android
- 2022-03-29 Python數據類型-序列sequence_python
- 2022-10-06 C++?pimpl機制詳細講解_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支