EventBus 3.0源码学习(二)

一、post和postSticky的区别

    /** Posts the given event to the event bus. */
    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List 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, 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).
                Set, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry, 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源码学习(二))