EventBus源码解读详细注释(4)register时刷新的两个map
2016-03-20 21:09
816 查看
[EventBus源码分析(一):入口函数提纲挈领(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51802172)
[EventBus源码分析(二):register方法保存事件的订阅者列表(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51819508)
[EventBus源码分析(三):post方法发布事件【获取事件的所有订阅者,反射调用订阅者事件处理方法】(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51821143)
[EventBus源码分析(四):线程模型分析(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51832001)
[EventBus源码解读详细注释(1)register的幕后黑手](http://blog.csdn.net/wangshihui512/article/details/50914817)
[EventBus源码解读详细注释(2)MainThread线程模型分析](http://blog.csdn.net/wangshihui512/article/details/50934012)
[EventBus源码解读详细注释(3)PostThread、MainThread、BackgroundThread、Async四种线程模式的区别](http://blog.csdn.net/wangshihui512/article/details/50935729)
[EventBus源码解读详细注释(4)register时刷新的两个map](http://blog.csdn.net/wangshihui512/article/details/50938663)
[EventBus源码解读详细注释(5)事件消息继承性分析 eventInheritance含义](http://blog.csdn.net/wangshihui512/article/details/50947102)
[EventBus源码解读详细注释(6)从事件发布到事件处理,究竟发生了什么!](http://blog.csdn.net/wangshihui512/article/details/50949960)
EventBus中有两个重要的map,一个是事件到订阅者列表的map,另一个是订阅者到事件列表的map,每次register的时候都要动态刷新这两个map的数据。正是因为有了这两个map,EventBus在post事件的时候才可以根据事件类型找到所有订阅了此事件的订阅者,然后使用反射调用订阅者的事件处理方法。先看看EventBus中这两个map是如何定义的
/*事件到订阅者列表的map,key是事件,也就是消息处理方法的参数的Class,value是所有的订阅此事件的订阅者列表*/ private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType; /*订阅者到订阅者订阅的所有事件列表的map,key是订阅者,value是该订阅者订阅的所有事件的列表*/ private final Map<Object, List<Class<?>>> typesBySubscriber;
在register的时候会动态的刷新这两个map,主要是刷新map的value即刷新列表。
private synchronized void register(Object subscriber, boolean sticky, int priority) { /*getClass():* Returns the unique instance of Class that represents this object's class.*/ /*过滤出订阅者的所有事件处理方法(包括父类的),以列表形式返回*/ List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass()); for (SubscriberMethod subscriberMethod : subscriberMethods) { /*遍历,对订阅者的每一个事件处理方法进行订阅*/ subscribe(subscriber, subscriberMethod, sticky, priority); } }
subscribe方法中主要做了一件事,就是更新那两个重要的map
/** * @param subscriber 订阅者 * @param subscriberMethod 订阅者的事件处理方法 * @param sticky 是否是粘性事件 * @param priority 优先级 */ // Must be called in synchronized block private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) { /*每次subscribe都要更新两个map,事件到订阅者列表的map,和订阅者到事件列表的map*/ /*下边的代码先更新事件到订阅者列表的map,主要是更新此事件的订阅者列表*/ /*获取消息类型,也就是事件处理方法的参数类型*/ Class<?> eventType = subscriberMethod.eventType; /*private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType; * subscriptionsByEventType: key:消息类型(事件处理方法参数类型),value:接受此消息类型的所有订阅者列表 * */ /*获取所有接受此消息类型的订阅者列表,然后把新的订阅者加入此列表*/ CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType); /*根据订阅者,事件、优先级封装一个新的订阅者封装类Subscription*/ Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority); /*如果此消息类型的订阅者列表为null,表示还没有订阅者订阅此类型消息,就创建一个订阅者列表*/ if (subscriptions == null) { subscriptions = new CopyOnWriteArrayList<Subscription>(); /*将事件和事件对应的订阅者列表加入全局的map*/ subscriptionsByEventType.put(eventType, subscriptions); } else { /*如果接收此消息类型的订阅者列表不为空,并且列表里边已经有此订阅者,抛出重复注册异常*/ if (subscriptions.contains(newSubscription)) { throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType); } } // Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again) // subscriberMethod.method.setAccessible(true); /*更新事件的订阅者列表*/ /*将新的注册的订阅者根据优先级插入到合适位置,priority表示优先级,按照该数值从大到小排列*/ int size = subscriptions.size(); for (int i = 0; i <= size; i++) { /*按照优先级遍历 逐个比较*/ if (i == size || newSubscription.priority > subscriptions.get(i).priority) { /*注意写时复制的思想,CopyOnWriteArrayList增加数据的源代码如下所示*/ /* public synchronized void add(int index, E e) { Object[] newElements = new Object[elements.length + 1]; public static native void arraycopy(Object src, int srcPos,Object dst, int dstPos, int length); * Copies length elements from the array src, * starting at offset srcPos, into the array dst, * starting at offset dstPos. * @param src the source array to copy the content. * @param srcPos the starting index of the content in {@code src}. * @param dst the destination array to copy the data into. * @param dstPos the starting index for the copied content in {@code dst}. * @param length the number of elements to be copied. System.arraycopy(elements, 0, newElements, 0, index); newElements[index] = e; System.arraycopy(elements, index, newElements, index + 1, elements.length - index); elements = newElements; } */ /*CopyOnWriteArrayList并不是按照数据结构里边将的那样通过数据移位来添加元素,那样效率太低了 * 而是先创建一个比原来列表size大1的新列表,将新添加数据前边的所有数据整体赋值到新列表前边, * 将要添加的新数添加在新列表的后边,然后把剩下的一起复制到新列表*/ subscriptions.add(i, newSubscription); break; } } /*然后接下来更新订阅者到事件列表的map,主要是更新事件列表*/ /*private final Map<Object, List<Class<?>>> typesBySubscriber; * typesBySubscriber :key订阅者 value订阅者订阅的消息列表 * typesBySubscriber是EventBus的成员属性,表示一个map,key是订阅者,value是该订阅者订阅的所有事件的列表, * 是全局的,要囊括所有订阅者 * subscriptionsByEventType也是EventBus的成员属性,表示一个map,key是事件,value是订阅了改事件的所有订阅者的列表, * 是全局的,要囊括所有事件*/ /*获取订阅者的接受的所有消息类型列表*/ List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber); /*如果此订阅者还没有以前没有订阅事件,则创建列表,添加事件*/ if (subscribedEvents == null) { subscribedEvents = new ArrayList<Class<?>>(); /*typesBySubscriber是EventBus的类成员*/ typesBySubscriber.put(subscriber, subscribedEvents); } /*将此事件添加到订阅者订阅的事件的列表,更新事件列表*/ subscribedEvents.add(eventType); /*处理粘性事件*/ if (sticky) { /*是否要考虑事件的继承性*/ if (eventInheritance) { // Existing sticky events of all subclasses of eventType have to be considered. // Note: Iterating over all events may be inefficient with lots of sticky events, // thus data structure should be changed to allow a more efficient lookup // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>). Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet(); for (Map.Entry<Class<?>, Object> entry : entries) { Class<?> candidateEventType = entry.getKey(); if (eventType.isAssignableFrom(candidateEventType)) { Object stickyEvent = entry.getValue(); checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } } else { Object stickyEvent = stickyEvents.get(eventType); checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } }
相关文章推荐
- 多线程状态介绍
- Intent传递序列化数据
- private、protected、default、public权限
- c#抽象类
- js设计模式-工厂模式(XHR工厂)
- Java 套接字使用
- 入门训练 序列求和
- 数据库-mongodb-索引
- 代码复审
- 20145317彭垚《Java程序设计》第3周学习总结
- 多元线性回归例子
- List、Set、Map相关Q&A
- C++继承和包含
- 一张图搞定Android学习路线,非常全面
- AJAX实现基于WEB的文件上传的进度控制
- C++继承和包含
- 猎豹MFC--MiNiMS管理系统
- 数据库-mongodb-高级查询表达式
- SQL一些问题
- 异或运算^和他的一个常用作用