您的位置:首页 > 其它

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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: