EventBus除了可以發送普通事件,還可以支持發送粘性事件,就是先發送事件之后再訂閱也能收到該事件,類似于粘性廣播,第三篇我們就來決議一下黏性事件的原理,
Android 輕量級執行緒間通信EventBus
Android EventBus保姆級原始碼決議(一)注冊方法register
Android EventBus保姆級原始碼決議(二)發送事件post
總結
慣例總結(太長不看版):
- 黏性事件是通過
stickyEvents這個Map去實作的 - 所有post/remove的黏性事件會被保存/洗掉到
stickyEvents - 當訂閱了黏性事件(Event)時,發現
stickyEvents中存在這個Event,則直接呼叫訂閱方法
使用黏性事件
首先我們回顧一下黏性事件的使用:
- 訂閱者訂閱粘性事件
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun XXX(MessageEvent messageEvent){
···
}
- 發送粘性事件
EventBus.getDefault().postSticky(new MessageEvent())
- 移除黏性事件
EventBus.getDefault().removeStickyEvent(new MessageEvent())
可以很明顯看到黏性事件和普通事件的區別在于訂閱時在注解中使用sticky = true、以及使用EventBus.postSticky方法,我們先看EventBus.postSticky有什么不同
EventBus.postSticky
/**
* Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky
* event of an event's type is kept in memory for future access by subscribers using {@link Subscribe#sticky()}.
*/
public void postSticky(Object event) {
// 獲取到鎖之后把事件put進黏性事件陣列stickyEvents
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// 直接呼叫post方法
post(event);
}
哦,原來EventBus.postSticky方法僅僅是在EventBus.post之前把黏性事件添加到stickyEvents佇列了而已,EventBus.post方法我們在上一篇中有詳細的講解
Android EventBus保姆級原始碼決議(二)發送事件post
第二篇post的決議中,并沒有發現對黏性事件的任何處理,那黏性事件是怎么實作的呢,仔細想想黏性事件的需求,先發送事件、再訂閱也能收到該事件,所以是不是訂閱的時候也有額外處理呢,沒錯第一篇register方法中我們挖了一個坑:
在訂閱時,Event.register會呼叫
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
...
Object stickyEvent = stickyEvents.get(eventType);
// post黏性事件
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
...
}
其中newSubscription就是當前訂閱類、訂閱方法的包裝類,checkPostStickyEventToSubscription來處理這個包裝類
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {
//如果黏性事件串列不為空直接呼叫postToSubscription
postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}
如果黏性事件串列不為空直接呼叫postToSubscription去在對應的執行緒呼叫訂閱方法,這個方法詳細決議也可以看第二篇,到此EventBus中所有呼叫黏性事件的方法就講完了
沒錯,就是這么簡單, Event通過維護幾個陣列
- 黏性陣列(
stickyEvent) - <訂閱class,<訂閱類,訂閱方法>list>的Map(
subscriptionsByEventType) - <訂閱類,訂閱的類串列>Map(
typesBySubscriber) - Local包裝的當前執行緒事件串列
currentPostingThreadState
這么簡單的完成了執行緒間的通信,使用起來很也無感、輕量,不得不讓人佩服作者的水平
那,這篇就到這了,其實EventBus中還有怎么通過反射獲取@Subscribe注解的方法、建筑者模式值得一講,那就有空再聊了(他挖坑一直可以的)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/387947.html
標籤:其他
上一篇:Kotlin協程+Retrofit=網路模塊開發最優解?
下一篇:RxJava使用與原理分析
