>,Object>stickyEvents:
维护的是粘性事件的集合,粘性事件也就是当event发送出去之后再注册粘性事件的话,该粘性事件也能接收到之前发送出去的event消息。
其次,初始化3个消息发送器如下:
mainThreadPoster:
该类继承自Handler,而且在EventBus中mainThreadPoster属于主线程Handler,这是因为mainThreadPoster就是为处理“消息接收方法在主线程而消息发送在子线程”这个问题而设计的,所以子线程向主线程发送消息必须使用主线程的Handler。
mainThreadPoster继承Handler也是为了效率考虑的。
backgroundPoster:
该类继承自Runnable,重写了run()方法。
在run()方法中将子线程中的消息通过EventBus发送到主线程。
所以这个消息发送器作用就是处理“消息接收方法在子线程接而消息的发布在主线程”这样的问题。
asyncPoster:
该类继承自Runnable,也重写了run()方法,不过就像名字一样“异步”,也就是说不管订阅者是不是在主线程,消息接收方法都会另外开启一个线程处理消息。
然后,一个重要的初始化对象为subscriberMethodFinder,这个对象利用反射的方法查找每一个接收消息者的方法(也即是添加了“@Subscribe”注解的方法)。
最后就是一些对EventBusBuilder的一些配置信息。
其中eventInheritance和executorService在接下来分析源码时会经常碰到:
①eventInheritance表示我们自定义的待发布消息事件是否允许继承,,默认情况下eventInheritance==true。
它的作用就是处理业务时后来新增加业务后不必再修改代码,只需要继承就OK啦(这也符合程序的“开闭原则”)如下:
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
publicclassMessageEvent{
publicfinalStringmessage;
publicMessageEvent(Stringmessage){
this.message=message;
}
}
publicclassSubMessageEventextendsMessageEvent{
publicSubMessageEvent(Stringmessage){
super(message);
}
}
②executorService:
这个线程池是给backgroundPoster和asyncPoster用来处理消息发送的。
这样做也能够提高消息发送的效率。
2、注册register(Objectsubscriber)
EventBus的初始化工作已经完毕,我们继续看一下EventBus是怎么进行注册的,在注册过程中又搞了哪些事情?
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
publicvoidregister(Objectsubscriber){
Class
>subscriberClass=subscriber.getClass();
ListsubscriberMethods=subscriberMethodFinder
.findSubscriberMethods(subscriberClass);
synchronized(this){
for(SubscriberMethodsubscriberMethod:
subscriberMethods){
subscribe(subscriber,subscriberMethod);
}
}
}
在该方法中首先取得注册者的运行时类对象,拿到运行时类对象后通过注册者注册方法查找器SubscriberMethodFinder利用反射的方法找到注册者类中所有的接收消息的方法,也即是所有添加了注解“Subscribe”的方法。
最后进行通过方法subscribe(subscriber,subscriberMethod)为每一个接收消息的方法进行注册。
流程大致就是这样的,首先我们先看一下findSubscriberMethods这个方法:
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
/**
*方法描述:
获取该运行时类的所有@Subscribe注解的所有方法
*
*@paramsubscriberClass@Subscribe注解所属类的运行时类对象
*@return注册EventBus类中@Subscribe注解的所有方法的List集合
*/
ListfindSubscriberMethods(Class
>subscriberClass){
//先从缓存中查找是否存在消息接收的方法
ListsubscriberMethods=METHOD_CACHE.get(subscriberClass);
if(subscriberMethods!
=null){
returnsubscriberMethods;
}
if(ignoreGeneratedIndex){
//使用反射方法拿到订阅者中的订阅方法
subscriberMethods=findUsingReflection(subscriberClass);
}else{
//使用apt处理器拿到订阅者中的订阅方法
subscriberMethods=findUsingInfo(subscriberClass);
}
//如果该消息事件没有被订阅则抛出异常
if(subscriberMethods.isEmpty()){
thrownewEventBusException("Subscriber"+subscriberClass
+"anditssuperclasseshavenopublicmethodswiththe@Subscribeannotation");
}else{
//将查到的方法放到缓存中,以便下次使用
METHOD_CACHE.put(subscriberClass,subscriberMethods);
returnsubscriberMethods;
}
}
这个方法很重要,在初次使用EventBus3.0的时候也容易出错的一个点(3.0新增注解):
就是在订阅事件的方法上没有添加@Subscribe注解,所以会碰到下面这个异常:
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
Causedby:
org.greenrobot.eventbus.EventBusException:
SubscriberclassXXXanditssuperclasses
havenopublicmethodswiththe@Subscribeannotation
说到这我们还是没有最终看到EventBus是怎么进行注册的,OK,回过头来我们继续看注册:
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
privatevoidsubscribe(Objectsubscriber,SubscriberMethodsubscriberMethod){
Class
>eventType=subscriberMethod.eventType;
Log.e(TAG,eventType.getSimpleName());
//将订阅类Object对象subscriber封装为EventBus的订阅类Subscription
SubscriptionnewSubscription=newSubscription(subscriber,subscriberMethod);
CopyOnWriteArrayListsubscriptions=subscriptionsByEventType.get(eventType);
if(subscriptions==null){
subscriptions=newCopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType,subscriptions);
}else{
if(subscriptions.contains(newSubscription)){
thrownewEventBusException("Subscriber"+subscriber.getClass()+"alreadyregisteredtoevent"
+eventType);
}
}
/**
*方法描述:
对CopyOnWriteArrayList中的Subscription根据优先级的高低重新进行排序
*/
intsize=subscriptions.size();
for(inti=0;i<=size;i++){
if(i==size||subscriberMethod.priority>subscriptions.get(i).subscriberMethod.priority){
subscriptions.add(i,newSubscription);
break;
}
}
/**
*方法描述:
将开发者注册EventBus的类的运行时类添加到subscribedEvents中,并且把该运行时类添加到
*typesBySubscriber中
*/
List>>subscribedEvents=typesBySubscriber.get(subscriber);
Log.e(TAG,"typesBySubscriber的");
if(subscribedEvents==null){
subscribedEvents=newArrayList<>();
typesBySubscriber.put(subscriber,subscribedEvents);
}
subscribedEvents.add(eventType);
if(subscriberMethod.sticky){
if(eventInheritance){
//ExistingstickyeventsofallsubclassesofeventTypehavetobeconsidered.
//Note:
Iteratingoveralleventsmaybeinefficientwithlotsofstickyevents,
//thusdatastructureshouldbechangedtoallowamoreefficientlookup
//(e.g.anadditionalmapstoringsubclassesofsuperclasses:
Class->List).
Set>,Object>>entries=stickyEvents.entrySet();
for(Map.Entry>,Object>entry:
entries){
Class
>candidateEventType=entry.getKey();
if(eventType.isAssignableFrom(candidateEventType)){
ObjectstickyEvent=entry.getValue();
checkPostStickyEventToSubscription(newSubscription,stickyEvent);
}
}
}else{
ObjectstickyEvent=stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription,stickyEvent);
}
}
}
上面的这段代码虽然很多,但主要做了几件事情:
①将注册的订阅者封装为新的Subscription类②将订阅者存储到Map集合subscriptionsByEventType当中③对消息事件接收者根据优先级进行重排序④添加粘性消息事件
发布消息:
我们已经分析完了EventBus的注册过程,接下来我们再来分析一下EventBus的事件发送过程。
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
EventBus.getDefault().post(event);
那么这段代码是如何实现消息的发送呢?
继续源码看一下:
[html]viewplaincopy在CODE上查看代码片派生到我的代码片
publicvoidpost(Objectevent){
PostingThreadStatepostingState=currentPostingThreadState.get();
List
eventQueue.add(event);//将该事件添加到事件队列当中
//事件没有分发则开始分发
if(!
postingState.isPosting){
//判断消息接收者是否在主线程
postingState.isMainThread=Looper.getMainLooper()==Looper.myLooper();
postingState.isPosting=true;
if(postingState.canceled){
thrownewEventBusException("Internalerror.Abortstatewasnotreset");
}
try{
//循环发送消息
while(!
eventQueue.isEmpty()){
postSingleEvent(eventQueue.remove(0),postingState);
}
}finally{
postingState.isPosting=false;
postingState.isMainThread=false;
}
}
}
从上面的代码中可以得知,待发送的消息首先存储到一个消息list集合当中,然后再不断的循环发送消息。
发送消息时利用的方法是postSingleEvent(Objectevent,PostingThreadStatepostingState),OK,我们继续跟进:
privatevoidpostSingleEvent(Objectevent,PostingThreadStatepostingState)throwsError{
Class
>Class=event.getClass();
booleansubscriptionFound=false;
//默认情况下Event事件允许继承,即默认情况下eventInheritance==true
if(eventInheritance){
//查找event事件及event子类事件
List>>eventTypes=lookupAllEventTypes(eventClass);
intcountTypes=eventTypes.s