之前介绍过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
事件总线却简单了,大大提高了我们的开发效率。