EventBus 3.0源码学习(二)

来源:互联网 发布:氮氧化物历年排放数据 编辑:程序博客网 时间:2024/06/08 06:40

一、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}
原创粉丝点击