之前介绍过EventBus的使用,如果不知道如何使用的,可以参考我的这篇文章《EventBus使用详解》,个人觉得EventBus的用法简单方便,是非常棒的事件总线。
接下来,带大家好好的解析一下EventBus的源码,看下EventBus是如何实现订阅/发布事件的。本文主要从基本流程上解析。
这是我分析过程中,对EventBus理解的主要信息存储类,以及他们之间的查找流程。基本上他们是按照这个流程查找到订阅方法,然后通过反射进行发布事件,在相应的订阅方法进行事件的响应。
EventBus.getDefault()
getDefault方法:初始化EventBus,并且使用单例模式实现,主要做的事情就是初始化,包括:EventBusBuilder、映射池等。
以上的截图基本上我已经做了注释,DEFAULT_BUILDER就是new了一个EventBusBuilder对象,EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();基本上EventBus所需要的信息都已经初始化好的了。
register
EventBus的注册方法
首先通过subscriberMethodFinder.findSubscriberMethods获取注册类的所有注册方法
findSubscriberMethods方法:
这里首先查找方法缓存池中有没有该注册类的订阅方法,如果有就直接返回,如果没有就通过findUsingInfo(subscriberClass)方法找出该注册类的订阅方法,查找到该订阅方法之后就会将方法缓存到方法缓存池中。
findUsingInfo方法:
首先获取FindState对象,并且将subscriberClass订阅传入initForSubscriber方法,初始化findState。而clazz就是我们传入的subscriberClass,通过getSubscriberInfo获取订阅信息为null
继续分析findUsingInfo方法,应为findState.subscriberInfo为null,所有通过findUsingReflectionInSingleClass(findState)方法获取订阅信息和订阅方法。然后通过getMethodsAndRelease(findState)返回该订阅类的所有订阅方法。
findUsingReflectionInSingleClass(findState)方法
最后通过findUsingReflectionInSingleClass(findState)获取订阅类的所有订阅方法,因此我们重点看下这个方法的实现。
首先通过getDeclaredMethods()获取该订阅类的自身声明的所有方法,然后通过遍历查找:修饰符为:public,不是static和abstract类型的方法,并且同时:方法参数只有一个,且注解类型为Subscribe的方法。最后将方法method、事件类型eventType、线程模式threadMode等信息存入一个名为SubscriberMethod的信息类存储。并且将该信息类加入到findState.subscriberMethods方法集合。这里的eventType就是使用方法的参数作为事件类型:在发布事件中作用非常之大。
我们继续看回findUsingInfo方法,最后两个步骤调用moveToSuperclass()方法和getMethodsAndRelease(findState)方法
moveToSuperclass():
getMethodsAndRelease(findState):
主要做的事情就是释放findState并且返回subscriberMethods订阅方法的集合。
findState.recycle():
以上就是根据订阅类查找订阅方法的过程。有不明白的地方,可以看注释。
继续看回register注册方法。
获取得到订阅类的订阅方法之后,就会遍历订阅方法集合,逐一进行订阅。接下来看subscribe订阅方法。
subscribe订阅方法
以上的截图就是subscribe订阅方法。主要做的事情只有三件:1)、将事件类型(eventType)和订阅信息集合(CopyOnWriteArrayList)加入到订阅类型和订阅信息集合的映射池(subscriptionsByEventType);
2)、将订阅类(subscriber)和订阅类型集合(List<Class<?>> subscribedEvents)加入到订阅类型集合和订阅类的映射池;
3)、粘性事件加入到粘性事件集合。粘性事件会优先获取发布checkPostStickyEventToSubscription。
以上就是订阅的整个过程了。
unregister注销过程
1、根据订阅类得到订阅类型集合
2、将订阅类型集合遍历,调用unsubscribeByEventType注销。
1、根据订阅类型获取订阅信息的集合
2、将订阅信息集合进行遍历,完成注销。
post 发布过程
这里主要看postSingleEvent(eventQueue.remove(0), postingState)分发消息的方法,而currentPostingThreadState就是ThreadLocal,关于ThreadLocal的作用,大家可以另查资料。
接下来我们查看分发消息的流程。
postSingleEvent:
1)、lookupAllEventTypes(eventClass)根据事件类获取所有的事件类型。
2)、调用postSingleEventForEventType(event, postingState, clazz)方法进行事件分发。
postSingleEventForEventType:
1)、subscriptionsByEventType.get(eventClass)根据事件类型从订阅类型和订阅信息集合的映射池取出订阅信息集合。
2)、遍地订阅信息集合,调用postToSubscription方法对订阅信息进行分发。
postToSubscription :
这里主要是根据不同的线程模式进行分发事件,默认的模式是POSTING,然后调用invokeSubscriber方法分发。
invokeSubscriber:
1)、这是分发的最终调用的方法,拿到了订阅信息类subscription,订阅信息里面存放着subscriberMethod订阅方法。
2)、subscription.subscriberMethod.method.invoke(subscription.subscriber, event);使用反射进行事件分发。
至此,已经完成了这个订阅/发布的流程。虽然其内部的实现过程复杂,但是我们使用EventBus事件总线却简单了,大大提高了我们的开发效率。