EventBus浅析

在EventBus这个开源库中,一切都是围绕EventBus这个类来实现的。所以这次主要是看看EventBus这个类的基本原理。

从EventBus的使用方法可以看出,EventBus的初始化方法其实使用了单例模式,这也是EventBus能够在不同的类中响应post事件的前提。

每一个EventBus的使用基本都分为三部分,第一就是register方法,第二就是unregister方法,最后就是post方法。

首先看register方法的作用:
我们可以看到传入了一个Object类型的参数subscriber,再结合我们使用的时候的写法:
EventBus.getDefault().register(this)
我们可以知道这个传入的参数其实就是我们此时所在的类。在register方法中通过将subscriber.getClass()的返回对象(subscribe的类类型—和反射有关)传入subscriberMethodFinder类的findSubscriberMethods方法(它的实现逻辑),就可以获得在这个类中的所有EventBus事件响应方法subscriberMethod(类似: public void onEventMainThread(TestEvent event) {})队列,然后使用for循环遍历这个队列,为每一个事件响应方法执行subscribe方法,并将subscriber和此时的响应方法subscriberMethod作为参数。

subscribe方法中首先新建一个订阅者信息对象,这个对象保存有当前的类名以及此时对应传入的subscriberMethod响应事件方法名。然后会执行subscriptionsByEventType.get(eventType);这样的代码返回一个订阅者信息队列。当我们的程序执行到这个类的代码之前,如果没有执行过EventBus.getDefault().register(this)这样的代码,返回的列表会是空的,此时新建一个空列表,然后将这个空列表以及此时的响应方法方法名保存到subscriptionsByEventType这个HashMap中,可以看到此时的map对象中保存的list队列还是空的。之后,会在list的size的位置(比如如果为空,那么就是第0个位置)将前面新建的订阅者信息对象保存进去。就这样,每一个响应方法所产生的订阅者信息对象都会保存在list中,因为list是subscriptionsByEventType这个map的value,所以同样的也保存在了subscriptionsByEventType中(虽然list的数据是在map将list添加之后才初始化的,但是并不影响map中也能获取数据)。同样的还有typesBySubscriber这个map用来保存所有EventBus注册类所对应的的响应事件的参数实体Event的(比如上面的TestEvent)。

总而言之,上面的方法的主要作用就是为了获得subscriptionsByEventType和typesBySubscriber这两个HashMap对象。

subscriptionsByEventType存放所有的订阅者的信息,key值是eventType,value值是存放订阅者信息(当前register所在的类以及此时的方法名)list队列(用于post方法查询)
typesBySubscriber存放所有响应方法,key值是当前各个register所在的类,value值是存放eventType的队列(一般用于unregister)
再看看unregister方法,这个方法的传入参数和register一样,也是当前类。在这个类中首先通过当前类从typesBySubscriber中获得当前eventType的队列。通过for循环,将每个eventType,以及当前类传入unsubscribeByEventType这个方法中。在unsubscribeByEventType这个方法中,通过传入的eventType从subscriptionsByEventType这个map中取出对应的订阅者信息队列,然后取出每个订阅者信息对象,将他们一一移除。看到这里可以看出,如果在这个类执行完毕不执行unregister的话,下次再执行到这个类,就会再次在上面两个map中添加响应的信息,也就是说,事件响应方法会被执行多遍,显然这是不被允许的(EventBus自身会管理,如果真的没有unregister就会报错)。

最后看看post方法,可以看到post方法会调用postSingleEvent方法,接着postSingleEvent方法回调用postSingleEventForEventType方法,这个方法会从subscriptionsByEventType这个map中取出所有的订阅者信息对象,然后使用for循环,在循环中会调用postToSubscription方法,而post方法主要实现逻辑就是这个postToSubscription方法。在这个方法中则会根据当前订阅者信息对应的响应事件方法的一个threadMode属性,判断当前响应事件方法会在哪个模式下执行,一般是通过Poster发送数据或者通过订阅者信息中方法名的反射invoke方法来立即执行这个方法。

Poster类可以分为三种,都继承自runnable,最终都是通过PendingPost来加入执行队列,并在run方法中实现了pendingPost的是通过什么方式来实现的,通过EventBus的getExecutorService来执行本身的run方法。