EventBus除了可以发送普通事件,还可以支持发送粘性事件,就是先发送事件之后再订阅也能收到该事件,类似于粘性广播,第三篇我们就来解析一下黏性事件的原理。
Android 轻量级线程间通信EventBus
Android EventBus保姆级源码解析(一)注册方法register
Android EventBus保姆级源码解析(二)发送事件post
Android EventBus保姆级源码解析(三)黏性事件原理
惯例总结(太长不看版):
stickyEvents
这个Map去实现的stickyEvents
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
有什么不同
/**
* 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
方法我们在上一篇中有详细的讲解
第二篇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
)subscriptionsByEventType
)typesBySubscriber
)currentPostingThreadState
这么简单的完成了线程间的通信,使用起来很也无感、轻量,不得不让人佩服作者的水平
那,这篇就到这了,其实EventBus中还有怎么通过反射获取@Subscribe
注解的方法、建筑者模式值得一讲,那就有空再聊了(他挖坑一直可以的)