eventBus源码解析
EventBus定义:是一个发布 / 订阅的事件总线。 发布者,订阅者,事件,总线。
EventBus,可以说,就是在一个单例内部维持着一个map对象存储了一堆的方法;post无非就是根据参数去查找方法,进行反射调用
首先注册
EventBus.getDefault().register(this);//订阅事件
EventBus.getDefault().post(object);//发布事件
EventBus.getDefault().unregister(this);//取消订阅
onEventMainThread() 该方法执行对数据的绑定
如果方法名以onEvent开头,则代表要订阅一个事件,MainThread意思,这个方法最终要在UI线程执行;当事件发布的时候,这个方法就会被执行。
在onCreate里面执行EventBus.getDefault().register(this);意思是让EventBus扫描当前类.把所有onEvent开头的方法记录下来,如何记录呢?使用Map,Key为方法的参数类型,Value中包含我们的方法。
当子线程执行完毕,调用EventBus.getDefault().post(new ItemListEvent(Item.ITEMS))时,EventBus会根据post中实参的类型,去Map中查找对应的方法,于是找到了我们的onEventMainThread,最终调用反射去执行我们的方法。
EventBus的ThreadMode
EventBus包含4个ThreadMode:PostThread,MainThread,BackgroundThread,AsyncThread;
onEventMainThread 代表这个方法会在UI线程执行
onEventPostThread 代表这个方法会在当前发布事件的线程执行
onEventBackgroundThread 这个方法,如果在非UI线程发布的事件,则直接执行,和发布在同一个线程中。如果在UI线程发布的事件,则加入后台任务队列,使用线程池一个接一个调用。
onEventAsyncThread 加入后台任务队列,使用线程池调用,注意没有BackgroundThread中的一个接一个。
本质上调用的同一个
subscriber 是我们扫描类的对象,也就是我们代码中常见的this;
methodName 这个是写死的:“onEvent”,用于确定扫描什么开头的方法,可见我们的类中都是以这个开头。
sticky 这个参数,解释源码的时候解释,暂时不用管
priority 优先级,优先级越高,在调用的时候会越先调用。
调用内部类SubscriberMethodFinder的findSubscriberMethods方法,传入了subscriber 的class,以及methodName,返回一个List。
22行:看到没,clazz.getMethods();去得到所有的方法:
23-62行:就开始遍历每一个方法了,去匹配封装了。
25-29行:分别判断了是否以onEvent开头,是否是public且非static和abstract方法,是否是一个参数。如果都复合,才进入封装的部分。
32-45行:也比较简单,根据方法的后缀,来确定threadMode,threadMode是个枚举类型:就四种情况。
最后在54行:将method, threadMode, eventType传入构造了:new SubscriberMethod(method, threadMode, eventType)。添加到List,最终放回。
扫描了所有的方法,把匹配的方法最终保存在subscriptionsByEventType(Map,key:eventType ; value:CopyOnWriteArrayList)中;
eventType是我们方法参数的Class,Subscription中则保存着subscriber, subscriberMethod(method, threadMode, eventType), priority;包含了执行改方法所需的一切。
regist完毕后,如何post呢?
post方法中有一个PostingThreadState包含了一个eventQueue和一些标志位。
currentPostingThreadState是一个ThreadLocal类型的,里面存储了PostingThreadState;
post会根据实参去map查找进行反射调用