美文网首页程序员
EventBus 3.0源码学习(二)

EventBus 3.0源码学习(二)

作者: Mr_Dream | 来源:发表于2017-07-06 13:01 被阅读0次

    一、post和postSticky的区别

        /** Posts the given event to the event bus. */
        public void post(Object event) {
            PostingThreadState postingState = currentPostingThreadState.get();
            List<Object> eventQueue = postingState.eventQueue;
            eventQueue.add(event);
    
            if (!postingState.isPosting) {
                postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
                postingState.isPosting = true;
                if (postingState.canceled) {
                    throw new EventBusException("Internal error. Abort state was not reset");
                }
                try {
                    while (!eventQueue.isEmpty()) {
                        postSingleEvent(eventQueue.remove(0), postingState);
                    }
                } finally {
                    postingState.isPosting = false;
                    postingState.isMainThread = false;
                }
            }
        }
    
       public void postSticky(Object event) {
            synchronized (stickyEvents) {
                stickyEvents.put(event.getClass(), event);
            }
            // Should be posted after it is putted, in case the subscriber wants to remove immediately
            post(event);
        }
    
    从上面的比较来看postSticky利用 Map<Class<?>, Object> 数据结构来存储sticky事件,再调用post方法。接下去就是等待时机触发
    了,这个时机就是等待注册的那个时候,然后标有sticky标记的方法就好被触发执行。
    在EventBus类中有一个subscribe方法里面有如下的一段代码,这段主要是判断是否是黏性事件,如果是的话就执行,不是的话直接跳过。
    
     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);
                }
            }
    

    其实post和postSticky的区别用通俗的话来讲就是post要先注册,然后立刻开始处理事件对象。而postSticky就是不管你有没有注册,先发送事件对象再说,然后存储起来,直到有对象来注册这个sticky事件。

    二、其它类分析

    订阅方法类:主要用来存储订阅方法的相关信息。

    //有方法、线程模型、事件类型、优先级、粘性等属性。
    public class SubscriberMethod {
        final Method method;
        final ThreadMode threadMode;
        final Class<?> eventType;
        final int priority;
        final boolean sticky;
        /** Used for efficient comparison */
        String methodString;
    }
    
    

    订阅者信息类,用来存储订阅者和订阅方法。

    final class Subscription {
        final Object subscriber;
        final SubscriberMethod subscriberMethod;
        /**
         * Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery
         * {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
         */
        volatile boolean active;
    }
    

    EventBus的事件处理函数通常需要指定处理线程,EventBus提供了四种线程模型POSTING(默认)、MAIN、BACKGROUND、ASYNC

    public enum ThreadMode {
      //POSTING表示如果使用事件处理函数指定了线程模型为PostThread,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为PostThread的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。
        POSTING,
        
    //如果使用事件处理函数指定了线程模型为MainThread,那么不论事件是在哪个线程中发布出来的,该事件处理函数都会在UI线程中执行。该方法可以用来更新UI,但是不能处理耗时操作。
        MAIN,
    
    //如果使用事件处理函数指定了线程模型为BackgroundThread,那么如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作
        BACKGROUND,
    
      //如果使用事件处理函数指定了线程模型为Async,那么无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行。同样,此事件处理函数中禁止进行UI更新操作
        ASYNC
    }
    

    相关文章

      网友评论

        本文标题:EventBus 3.0源码学习(二)

        本文链接:https://www.haomeiwen.com/subject/plshhxtx.html