码迷,mamicode.com
首页 > 其他好文 > 详细

EventBus源码阅读(三)—— 订阅

时间:2016-04-21 06:55:44      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:

  经过订阅之后的类,才会接受到EventBus,post出来的消息。所以今天我们来看一下订阅的流程。

EventBus.getDefault().register(this);
    /**
     * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
     * are no longer interested in receiving events.
     * <p/>
     * Subscribers have event handling methods that must be annotated by {@link Subscribe}.
     * The {@link Subscribe} annotation also allows configuration like {@link
     * ThreadMode} and priority.
     */
    public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

 

  这个方法比较简单就是从类中寻找到订阅的方法,然后执行 subscribe(subscriber, subscriberMethod);订阅操作。

  subscribe方法的实现比较长,我们分块儿来看:  

        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList<>();
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }

        int size = subscriptions.size();
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                subscriptions.add(i, newSubscription);
                break;
            }
        }

 

 

  首先,subscribe中新建了一个Subscription,用来存放订阅者和订阅者的方法。然后,通过订阅者的订阅模式,寻找到该模式下已经存在订阅者队列——Subscriptions。如果是新建的Subscriptions就直接加入,如果已经存在,则抛出异常。接着,以订阅方法的priority为依据,将Subscription加入Subscriptions。

 

        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);

  这一段代码确定了当前订阅源有没有已经存在的事件列表,如果已经存在,直接加入,如果没有,新建一个加入。typesBySubscriber会用来判断订阅源是否已注册。

        if (subscriberMethod.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);
            }
        }
    }

  最后是一段关于粘性事件的处理,在此不做深究。

 

  可以看到,EventBus的订阅与发送事件最终的桥梁,就是subscriptionsByEventType。发送事件中

 

    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted = false;
                try {
                    postToSubscription(subscription, event, postingState.isMainThread);
                    aborted = postingState.canceled;
                } finally {
                    postingState.event = null;
                    postingState.subscription = null;
                    postingState.canceled = false;
                }
                if (aborted) {
                    break;
                }
            }
            return true;
        }
        return false;
    }

 

  订阅过程中,就是将订阅源放入subscriptionsByEventType中。

   

  初步的阅读过程,到这里,下一次来看一看粘性事件的实现。

 

  Done~

EventBus源码阅读(三)—— 订阅

标签:

原文地址:http://www.cnblogs.com/fishbone-lsy/p/5415280.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!