EventBus
大大大大大發表於2019-11-23
一、原理
1、註冊 EventBus.getDefault().register()
- 使用反射,在註冊的時候(EventBus.getDefault().register(this)),獲取類物件中被註解Subscribe註解的方法。
- 使用兩個HashMap儲存資訊。這樣可以 物件-》方法引數-》方法
- subscriptionsByEventType是一個HashMap,儲存了以eventType(方法引數型別)為key,Subscription物件(方法包裝物件)集合為value的鍵值對。
- typesBySubscribere也是一個HashMap,儲存了以當前要註冊類的物件為key,註冊類中訂閱事件的方法的引數型別的集合為value的鍵值對
- 如果有粘性事件的訂閱,會查詢stickyEvents這個HashMap集合,在進行方法註冊的時候就執行一次。
2、取消註冊 EventBus.getDefault().unregister()
- 先找出物件註冊的方法的引數型別,List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
- 再遍歷subscribedTypes,找出符合引數型別的list。 List subscriptions = subscriptionsByEventType.get(eventType);
- 上述兩個HashMap 對應註冊時存資訊的兩個,typesBySubscriber和subscriptionsByEventType
- 遍歷獲取的封裝方法物件,去掉需要取消註冊的物件的相關資訊
3、傳送事件 EventBus.getDefault().post("Hello World!")
- 根據引數型別,先把時間post到ThreadLocal物件的佇列中,再迴圈獲取該佇列中的事件,處理。
- 處理的過程是先獲取到該事件型別的訂閱者列表,再遍歷這些訂閱者,根據訂閱者資訊(最主要的是執行的執行緒資訊threadMode)進行反射執行方法。
4、傳送粘性事件 EventBus.getDefault().postSticky("Hello World!")
- 把事件存在stickyEvents這個集合中。
- 走一遍post()方法。就是第三步中普通的傳送事件流程
- 使用粘性事件注意處理好空指標異常。可能在註冊的時候就有事件執行,而某些用到的變數未初始化。