这一篇文章是基于上一篇文章的内容之上的的,在阅读这一篇文章之前请先阅读我的之前那篇文章EventBus源码解析(一)这里写链接内容
那么我们就马上进入主题吧,上篇文章分析到boolean sticky这个参数和registerSticky(Object subscriber)这个方法,这个方法与之前我们注册的方法是不是很像啊?
public void register(Object subscriber) {
this.register(subscriber, false, 0);
}
public void registerSticky(Object subscriber) {
this.register(subscriber, true, 0);
}
可以看出他们之间的区别了吗?在register()方法中,sticky被赋值为false,而registerSticky()方法将sticky被赋值为true。
后面的步骤跟上一篇文章中已经给大家分析的很清楚了,只有一个地方用到了sticky,让我们来看看是如何使用的吧:
if(sticky) {
Map var11 = this.stickyEvents;
Object stickyEvent;
synchronized(this.stickyEvents) {
stickyEvent = this.stickyEvents.get(eventType);
}
if(stickyEvent != null) {
this.postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}
显然只有当sticky被赋值为true的时候才会进入这个if判断语句,stickyEvents是一个map集合,如果stickyEvents是空的,那么这段代码看上去好像没有什么意义,那么我们来看看stickyEvents这个map集合是什么时候往里面添加数据的。
public void postSticky(Object event) {
Map var2 = this.stickyEvents;
synchronized(this.stickyEvents) {
this.stickyEvents.put(event.getClass(), event);
}
this.post(event);
}
原来是在postSticky(Object event)这个方法里添加的,原来registerSticky(Object subscriber)和postSticky(Object event)是一对啊!
等一下,为什么感觉有点奇怪呢,感觉是先发布,后注册!postSticky()这个方法好像在registerSticky()这个方法之前调用,因为只有你得先将数据添加到stickyEvents集合当中,然后才能从stickyEvents集合中获取到数据。
来分析一下吧,如果先发布postSticky(Object event),会将传入对象的Class作为Key,传入的对象作为值存入stickyEvents集合中,然后调用post(event),之前我们分析过了,post(event)主要是找到subscriptionsByEventType这个集合去取值,然后通过反射去调用相应的方法,但是这里我们都还没有注册,所以subscriptionsByEventType这个集合肯定是没有数据的,因此按理说是不会调用方法的,but但是还记得当我们注册的时候使用的是registerSticky()这个方法时不是有这段代码吗stickyEvent = this.stickyEvents.get(eventType);
这个时候stickyEvents集合里面是有数据的啊,那么stickyEvent 就不为null了,在往下看:
if(stickyEvent != null) {
this.postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
进入到这个if()判断语句当中,会调用postToSubscription这个方法,
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch(EventBus.SyntheticClass_1.$SwitchMap$de$greenrobot$event$ThreadMode[subscription.subscriberMethod.threadMode.ordinal()]) {
case 1:
this.invokeSubscriber(subscription, event);
break;
case 2:
if(isMainThread) {
this.invokeSubscriber(subscription, event);
} else {
this.mainThreadPoster.enqueue(subscription, event);
}
break;
case 3:
if(isMainThread) {
this.backgroundPoster.enqueue(subscription, event);
} else {
this.invokeSubscriber(subscription, event);
}
break;
case 4:
this.asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
我想问这个方法你熟不熟?很熟了吧,不就是找到了对应的subscription对象通过反射调用对应的方法吗?现在你知道这个Boolean sticky是干什么用的了吧,它可以让我们倒着使用EventBus,这么说好像不太通俗,就是你可以先发布事件,我稍后注册依然可以找到你并调用对应的方法来实现通信的功能,但是跟先注册后发布还是有区别的,这次我并不是从subscriptionsByEventType拿到的数据,而是从stickyEvents这个集合中拿到的数据哦!
这篇文章就分析到这里了,通过这两篇文章来总结一下EventBus:
它既可以先注册,然后再发布对象,也可以先发布对象,后注册调用相应的方法。
还有就是在项目中使用EventBus时我曾经踩过一个坑,当时线程我们封装起来了,结果post(Object event)是在子线程中调用的,而我却在onEventMainThread()中写代码…….. 这里一定要注意,在那个线程发布事件,就要在对应的方法中写代码,好了,通过这两篇文章,EventBus源码的已经分析完了,希望这两篇文章能帮到大家的同时让自己的思路也更加清晰。