EventBus源码解读详细注释(4)register时刷新的两个map

[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);
            }
        }
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值