Eventbus最强解析

914 阅读11分钟

使用

image.png

  1. 导入EventBus
implementation("org.greenrobot:eventbus:3.3.1")
  1. 定义事件
public static class MessageEvent {
    /* Additional fields if needed */ 
}
  1. 注册和解注册
@Override
 public void onStart() {
     super.onStart();
     EventBus.getDefault().register(this);
 }

 @Override
 public void onStop() {
     super.onStop();
     EventBus.getDefault().unregister(this);
 }
  1. 监听事件
@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {
    // Do something
}
  1. 发送事件
EventBus.getDefault().post(new MessageEvent());

核心架构

image.png

源码解析

初始化

EventBus.getDefault().register(this);

看下getDefault方法

public static EventBus getDefault() {
    EventBus instance = defaultInstance;
    if (instance == null) {
        synchronized (EventBus.class) {
            instance = EventBus.defaultInstance;
            if (instance == null) {
                instance = EventBus.defaultInstance = new EventBus();
            }
        }
    }
    return instance;
}

很简单,返回一个单例。

看下构造方法。

public EventBus() {
    this(DEFAULT_BUILDER);
}

为什么构造方法是public的?

在我们项目中,并不是仅仅存在一条总线,也存在其它的总线。因此,我们订阅者也可以订阅到其它的总线之上,然后通过不同的EventBus发送数据。那么,我们需要注意的是,不同的EventBus发送的数据,是相互隔离开来的,订阅者只会收到注册到当前的EventBus发送的数据。

这样做的好处个人感觉有两点:

  1. 解耦
  2. 提高效率。项目大的时候索引搜索也是需要时间的。

成员变量

EventBus(EventBusBuilder builder) {
    (1)日志打印
    logger = builder.getLogger();
    (2)eventType 为Key, 订阅者和订阅者方法封装类为Value的map。
    subscriptionsByEventType = new HashMap<>();
    (3)订阅者为Key,eventType为Value的map。
    typesBySubscriber = new HashMap<>();
    (4)粘性事件
    stickyEvents = new ConcurrentHashMap<>();
    (5)切换主线程
    mainThreadSupport = builder.getMainThreadSupport();
    (6)将事件发送到主线程的Handler。
    mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
    (7)将事件发送到子线程的,通过线程池实现。
    backgroundPoster = new BackgroundPoster(this);
     (8) 将事件发送到子线程的,通过线程池实现。和上面的区别看下具体实现
    asyncPoster = new AsyncPoster(this);
    (9)订阅者数量
    indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
    (10)@Subscribe注解方法找寻器
    subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
            builder.strictMethodVerification, builder.ignoreGeneratedIndex);
    (11)当调用事件处理函数时,若发生了异常是否进行异常信息打印。默认true
    logSubscriberExceptions = builder.logSubscriberExceptions;
    (12)当没有订阅者订阅该事件时,是否打印日志。默认true
    logNoSubscriberMessages = builder.logNoSubscriberMessages;
    (13)当调用事件处理函数时,若发生了异常是否发送SubscriberExceptionEvent这个事件。默认true
    sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
    (14)当没有订阅者订阅该事件时,是否发送NoSubscriberEvent事件。默认true
    sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
    (15)是否抛出SubscriberException异常。默认false
    throwSubscriberException = builder.throwSubscriberException;
    (16)与event有继承关系的是否都需要发送。默认true
    eventInheritance = builder.eventInheritance;
    (17)执行服务线程池
    executorService = builder.executorService;
}

线程切换

  1. mainThreadPoster
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;

public class DefaultAndroidMainThreadSupport implements MainThreadSupport {

    @Override
    public boolean isMainThread() {
        return Looper.getMainLooper() == Looper.myLooper();
    }

    @Override
    public Poster createPoster(EventBus eventBus) {
        return new HandlerPoster(eventBus, Looper.getMainLooper(), 10);
    }
}

重点看下HandlerPoster

public class HandlerPoster extends Handler implements Poster {

    (1PendingPost的队列
    private final PendingPostQueue queue;
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
     (2) Handler是否可用
    private boolean handlerActive;

    public HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
        super(looper);
        this.eventBus = eventBus;
        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        (2)从缓存池获取一个PendingPost
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                handlerActive = true;
                (3)发送消息,会调用handleMessage,切换回主线程,
                if (!sendMessage(obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

    @Override
    public void handleMessage(Message msg) {
        boolean rescheduled = false;
        try {
            long started = SystemClock.uptimeMillis();
            (4while循环从队列里面依次取出
            while (true) {
                PendingPost pendingPost = queue.poll();
                (5)通过double check判断队列是否为空
                if (pendingPost == null) {
                    synchronized (this) {
                        // Check again, this time in synchronized
                        pendingPost = queue.poll();
                        if (pendingPost == null) {
                            handlerActive = false;
                            return;
                        }
                    }
                }
                (6)通过反射来完成事件分发
                eventBus.invokeSubscriber(pendingPost);
                long timeInMethod = SystemClock.uptimeMillis() - started;
                (7)事件分发时间大于最大值就返回。
                if (timeInMethod >= maxMillisInsideHandleMessage) {
                    if (!sendMessage(obtainMessage())) {
                        throw new EventBusException("Could not send handler message");
                    }
                    rescheduled = true;
                    return;
                }
            }
        } finally {
            handlerActive = rescheduled;
        }
    }
}
  1. backgroundPoster
final class BackgroundPoster implements Runnable, Poster {

    private final PendingPostQueue queue;
    private final EventBus eventBus;
    (1)线程池是否在运行
    private volatile boolean executorRunning;

    BackgroundPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!executorRunning) {
                executorRunning = true;
                eventBus.getExecutorService().execute(this);
            }
        }
    }

    @Override
    public void run() {
        try {
            try {
                while (true) {
                    PendingPost pendingPost = queue.poll(1000);
                    if (pendingPost == null) {
                        synchronized (this) {
                            // Check again, this time in synchronized
                            pendingPost = queue.poll();
                            if (pendingPost == null) {
                                executorRunning = false;
                                return;
                            }
                        }
                    }
                    ()通过反射执行
                    eventBus.invokeSubscriber(pendingPost);
                }
            } catch (InterruptedException e) {
                eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }

}
  1. AsyncPoster
class AsyncPoster implements Runnable, Poster {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    AsyncPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        queue.enqueue(pendingPost);
        eventBus.getExecutorService().execute(this);
    }

    @Override
    public void run() {
        PendingPost pendingPost = queue.poll();
        if(pendingPost == null) {
            throw new IllegalStateException("No pending post available");
        }
        eventBus.invokeSubscriber(pendingPost);
    }

}

共同点:

  • 都是通过反射完成事件分发。

不同点:

  • HandlerPoster 通过Handle把任务切换到主线程,backgroundPoster AsyncPoster 通过线程池切换到子线程。

  • HandlerPoster,backgroundPoster 会一次把队列里面的都执行完,AsyncPoster一次只执行一个,适合执行耗时比较长的任务。

特别注意

  • HandlerPoster 每次执行事件分发都会判断时间是否大于最大值。大于就返回,重新开始。

Subscribe注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
    (1)线程模式,对应mainThreadPoster、backgroundPoster、asyncPoster这三个Poster
    ThreadMode threadMode() default ThreadMode.POSTING;

    /**
     * If true, delivers the most recent sticky event (posted with
     * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
     */2)是否是粘性事件 
    boolean sticky() default false;

    /** Subscriber priority to influence the order of event delivery.
     * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
     * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
     * delivery among subscribers with different {@link ThreadMode}s! */3)优先级,优先级高的先收到
    int priority() default 0;
}

看下ThreadMode

public enum ThreadMode {
    /**
     * Subscriber will be called directly in the same thread, which is posting the event. This is the default. Event delivery
     * implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for
     * simple tasks that are known to complete in a very short time without requiring the main thread. Event handlers
     * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
     */1)当前线程 
    POSTING,

    /**
     * On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is
     * the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event
     * is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread.
     * If not on Android, behaves the same as {@link #POSTING}.
     */2)主线程 
    MAIN,

    /**
     * On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN},
     * the event will always be queued for delivery. This ensures that the post call is non-blocking.
     */3)主线程按照顺序
    MAIN_ORDERED,

    /**
     * On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber methods
     * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
     * background thread, that will deliver all its events sequentially. Subscribers using this mode should try to
     * return quickly to avoid blocking the background thread. If not on Android, always uses a background thread.
     */4)子线程
    BACKGROUND,

    /**
     * Subscriber will be called in a separate thread. This is always independent from the posting thread and the
     * main thread. Posting events never wait for subscriber methods using this mode. Subscriber methods should
     * use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
     * of long running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus
     * uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications.
     */5)单独子线程
    ASYNC
}

还是比较简单的。

可以参照使用看下。

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
    switch (subscription.subscriberMethod.threadMode) {
        case POSTING:
            invokeSubscriber(subscription, event);
            break;
        case MAIN:
            if (isMainThread) {
                invokeSubscriber(subscription, event);
            } else {
                mainThreadPoster.enqueue(subscription, event);
            }
            break;
        case MAIN_ORDERED:
            if (mainThreadPoster != null) {
                mainThreadPoster.enqueue(subscription, event);
            } else {
                // temporary: technically not correct as poster not decoupled from subscriber
                invokeSubscriber(subscription, event);
            }
            break;
        case BACKGROUND:
            if (isMainThread) {
                backgroundPoster.enqueue(subscription, event);
            } else {
                invokeSubscriber(subscription, event);
            }
            break;
        case ASYNC:
            asyncPoster.enqueue(subscription, event);
            break;
        default:
            throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
    }
}

注册

public void register(Object subscriber) {
    if (AndroidDependenciesDetector.isAndroidSDKAvailable() && !AndroidDependenciesDetector.areAndroidComponentsAvailable()) {
        // Crash if the user (developer) has not imported the Android compatibility library.
        throw new RuntimeException("It looks like you are using EventBus on Android, " +
                "make sure to add the "eventbus" Android library to your dependencies.");
    }
    (1)获取订阅者的Class对象
    Class<?> subscriberClass = subscriber.getClass();
    (2)找到当前订阅者的所有订阅方法
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

看下SubscriberMethod对象。

public class SubscriberMethod {
    (1)订阅的方法
    final Method method;
    (2)订阅的模式
    final ThreadMode threadMode;
    (3)事件类型
    final Class<?> eventType;
    (4)优先级
    final int priority;
    (5)是否是粘性事件
    final boolean sticky;
    /** Used for efficient comparison */6)判断是否是同一个方法,
    String methodString;

看下SubscriberMethodFinder成员变量。

class SubscriberMethodFinder {
    /*
     * In newer class files, compilers may add methods. Those are called bridge or synthetic methods.
     * EventBus must ignore both. There modifiers are not public but defined in the Java class file format:
     * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.6-200-A.1
     */
    private static final int BRIDGE = 0x40;
    private static final int SYNTHETIC = 0x1000;

    private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;
    (1)通过ConcurrentHashMap存储订阅类里面的所有订阅方法
    private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
    (2)订阅的索引
    private List<SubscriberInfoIndex> subscriberInfoIndexes;
    private final boolean strictMethodVerification;
    private final boolean ignoreGeneratedIndex;

    private static final int POOL_SIZE = 4;
    private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
}

看下findSubscriberMethods方法。

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    (1)先从缓存里面找到这个类的所有订阅方法,找到就直接返回
    List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
    if (subscriberMethods != null) {
        return subscriberMethods;
    }

    if (ignoreGeneratedIndex) {
        (2)通过反射查找
        subscriberMethods = findUsingReflection(subscriberClass);
    } else {
        (3)通过APT查找
        subscriberMethods = findUsingInfo(subscriberClass);
    }
    if (subscriberMethods.isEmpty()) {
        throw new EventBusException("Subscriber " + subscriberClass
                + " and its super classes have no public methods with the @Subscribe annotation");
    } else {
        (3)找到的方法放到缓存
        METHOD_CACHE.put(subscriberClass, subscriberMethods);
        return subscriberMethods;
    }
}

看下findUsingReflectionInSingleClass方法

private void findUsingReflectionInSingleClass(FindState findState) {
    Method[] methods;
    try {
        // This is faster than getMethods, especially when subscribers are fat classes like Activities1)获取所有声明的方法
        methods = findState.clazz.getDeclaredMethods();
    } catch (Throwable th) {
        // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
        try {
            (2)获取单签类的public方法,不包括父类
            methods = findState.clazz.getMethods();
        } catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...
            String msg = "Could not inspect methods of " + findState.clazz.getName();
            if (ignoreGeneratedIndex) {
                msg += ". Please consider using EventBus annotation processor to avoid reflection.";
            } else {
                msg += ". Please make this class visible to EventBus annotation processor to avoid reflection.";
            }
            throw new EventBusException(msg, error);
        }
        findState.skipSuperClasses = true;
    }
    (3)循环遍历
    for (Method method : methods) {
        (4)获取方法修饰符
        int modifiers = method.getModifiers();
        (5)如果是public类型,但非abstract、staticif ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
            (6)获得当前方法所有参数的类型
            Class<?>[] parameterTypes = method.getParameterTypes();
            (7)参数长度是1,因为Eventbus订阅只允许是1
            if (parameterTypes.length == 1) {
                (8)获取订阅方法的注解
                Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                if (subscribeAnnotation != null) {
                    Class<?> eventType = parameterTypes[0];
                    if (findState.checkAdd(method, eventType)) {
                        ThreadMode threadMode = subscribeAnnotation.threadMode();
                        findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                    }
                }
            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                throw new EventBusException("@Subscribe method " + methodName +
                        "must have exactly 1 parameter but has " + parameterTypes.length);
            }
        } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
            String methodName = method.getDeclaringClass().getName() + "." + method.getName();
            throw new EventBusException(methodName +
                    " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
        }
    }
}

看下findUsingInfo方法。

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
    (1)看下FindState,通过缓存池找到,找不到New一个。
    FindState findState = prepareFindState();
    (2)初始化订阅者Class对象
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        (3)获取subscriberInfo, 默认为null,实际会在Subscriber索引里面查找。
        findState.subscriberInfo = getSubscriberInfo(findState);
        if (findState.subscriberInfo != null) {
            (4)获取订阅者所有方法
            SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
            for (SubscriberMethod subscriberMethod : array) {
                if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                    findState.subscriberMethods.add(subscriberMethod);
                }
            }
        } else {
            (5)通过反射查找
            findUsingReflectionInSingleClass(findState);
        }
        (6)查找父类的
        findState.moveToSuperclass();
    }
    (7)返回找到的方法,并回收findState
    return getMethodsAndRelease(findState);
}

看下 FindState ,重点关注下 checkAdd 方法。

static class FindState {
    (1)订阅方法
    final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
    (2)订阅事件为Key,订阅方法为Value。
    final Map<Class, Object> anyMethodByEventType = new HashMap<>();
    (3)订阅方法为Key,订阅类的Class对象为Value。
    final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
    final StringBuilder methodKeyBuilder = new StringBuilder(128);

    Class<?> subscriberClass;
    Class<?> clazz;
    boolean skipSuperClasses;
    SubscriberInfo subscriberInfo;

    void initForSubscriber(Class<?> subscriberClass) {
        this.subscriberClass = clazz = subscriberClass;
        skipSuperClasses = false;
        subscriberInfo = null;
    }

    void recycle() {
        subscriberMethods.clear();
        anyMethodByEventType.clear();
        subscriberClassByMethodKey.clear();
        methodKeyBuilder.setLength(0);
        subscriberClass = null;
        clazz = null;
        skipSuperClasses = false;
        subscriberInfo = null;
    }

    (4)判断订阅方法是否添加到集合当中
    boolean checkAdd(Method method, Class<?> eventType) {
        // 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
        // Usually a subscriber doesn't have methods listening to the same event type.
        (5) 判断父类是否有订阅这个事件。
        Object existing = anyMethodByEventType.put(eventType, method);
        if (existing == null) {
            return true;
        } else {
            if (existing instanceof Method) {
                if (!checkAddWithMethodSignature((Method) existing, eventType)) {
                    // Paranoia check
                    throw new IllegalStateException();
                }
                // Put any non-Method object to "consume" the existing Method
                anyMethodByEventType.put(eventType, this);
            }
            return checkAddWithMethodSignature(method, eventType);
        }
    }

    (5) 判断是否子类订阅了
    private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
        methodKeyBuilder.setLength(0);
        methodKeyBuilder.append(method.getName());
        methodKeyBuilder.append('>').append(eventType.getName());

        String methodKey = methodKeyBuilder.toString();
        Class<?> methodClass = method.getDeclaringClass();
        Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
        if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
            // Only add if not already found in a sub class
            return true;
        } else {
            // Revert the put, old class is further down the class hierarchy
            subscriberClassByMethodKey.put(methodKey, methodClassOld);
            return false;
        }
    }

    void moveToSuperclass() {
        if (skipSuperClasses) {
            clazz = null;
        } else {
            clazz = clazz.getSuperclass();
            String clazzName = clazz.getName();
            // Skip system classes, this degrades performance.
            // Also we might avoid some ClassNotFoundException (see FAQ for background).
            if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") ||
                    clazzName.startsWith("android.") || clazzName.startsWith("androidx.")) {
                clazz = null;
            }
        }
    }
}

checkAdd这个方法主要两件事

  1. 判断方法FindState的anyMethodByEventType map是否已经添加过以当前eventType为key的键值对。

  2. 如果添加判断是否是子类添加的。

注册总结:

  1. 获取当前订阅者的Class对象。
  2. 通过反射或者通过索引找到当前对象的所有订阅方法。
  3. 每个方法一次遍历订阅。

订阅

// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    (1)获取订阅方法的订阅事件
    Class<?> eventType = subscriberMethod.eventType;
    (2)订阅者和订阅者方法构造Subscription对象
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    (3)通过订阅事件找到所有Subscription对象
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    if (subscriptions == null) {
        (4)没有找到就放入上面的Subscription对象
        subscriptions = new CopyOnWriteArrayList<>();
        subscriptionsByEventType.put(eventType, subscriptions);
    } else {
        (5)不为空就判断是否已经放入,不能多次放入(父子同时注册)
        if (subscriptions.contains(newSubscription)) {
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                    + eventType);
        }
    }

    (6)按照订阅事件的优先级插入合适的位置
    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;
        }
    }
    
    (7)找到当前订阅者所有的订阅事件
    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    subscribedEvents.add(eventType);

    (8)粘性事件
    if (subscriberMethod.sticky) {
        (9)是否支持继承关系,默认为trueif (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>).10)推荐,尤其是容量大时用entrySet遍历
            Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
            for (Map.Entry<Class<?>, Object> entry : entries) {
                Class<?> candidateEventType = entry.getKey();
                    (11) isAssignableFrom:判定此 Class 对象所表示的类
                    或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口。
                    如果是则返回 true;否则返回 falseif (eventType.isAssignableFrom(candidateEventType)) {
                    (12) 获取粘性事件
                    Object stickyEvent = entry.getValue();
                   (13)处理粘性事件
                    checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                }
            }
        } else {
            (14)获取粘性事件
            Object stickyEvent = stickyEvents.get(eventType);
            (15)处理粘性事件
            checkPostStickyEventToSubscription(newSubscription, stickyEvent);
        }
    }
}

订阅总结:

  1. 首先判断是否注册过这个事件。不允许多次注册。
  2. 按照订阅的优先级,添加到subscriptionsByEventType这个集合当中。
  3. 添加到typesBySubscriber这个Map当中。
  4. 如果是粘性事件,分发事件。

粘性事件

private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
    if (stickyEvent != null) {
        // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
        // --> Strange corner case, which we don't take care of here.
        postToSubscription(newSubscription, stickyEvent, isMainThread());
    }
}


private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
    switch (subscription.subscriberMethod.threadMode) {
        case POSTING:
            (1)直接反射分发,默认的线程模式,哪个线程发送就在哪个线程处理。
            invokeSubscriber(subscription, event);
            break;
        case MAIN:
            if (isMainThread) {
                invokeSubscriber(subscription, event);
            } else {
                mainThreadPoster.enqueue(subscription, event);
            }
            break;
        case MAIN_ORDERED:
            if (mainThreadPoster != null) {
                mainThreadPoster.enqueue(subscription, event);
            } else {
                // temporary: technically not correct as poster not decoupled from subscriber2)没有mainThreadPoster就直接反射。
                invokeSubscriber(subscription, event);
            }
            break;
        case BACKGROUND:
            if (isMainThread) {
                backgroundPoster.enqueue(subscription, event);
            } else {
                invokeSubscriber(subscription, event);
            }
            break;
        case ASYNC:
            asyncPoster.enqueue(subscription, event);
            break;
        default:
            throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
    }
}

void invokeSubscriber(Subscription subscription, Object event) {
    try {
        subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
    } catch (InvocationTargetException e) {
        handleSubscriberException(subscription, event, e.getCause());
    } catch (IllegalAccessException e) {
        throw new IllegalStateException("Unexpected exception", e);
    }
}

代码很简单,不做过多解释。

发送事件

EventBus.getDefault().post(new MessageEvent());

public void post(Object event) {
    (1)从ThreadLocal中获取PostingThreadState,看下PostingThreadState
    PostingThreadState postingState = currentPostingThreadState.get();
    List<Object> eventQueue = postingState.eventQueue;
    (2)添加到队列
    eventQueue.add(event);
    (3)是否正在发送
    if (!postingState.isPosting) {
        postingState.isMainThread = isMainThread();
        postingState.isPosting = true;
        if (postingState.canceled) {
            throw new EventBusException("Internal error. Abort state was not reset");
        }
        try {
            (4)将队列的事件全部分发
            while (!eventQueue.isEmpty()) {
                (5)重点看下postSingleEvent
                postSingleEvent(eventQueue.remove(0), postingState);
            }
        } finally {
            postingState.isPosting = false;
            postingState.isMainThread = false;
        }
    }
}

(1)当前线程Post信息的封装类
final static class PostingThreadState {
    (1)事件队列
    final List<Object> eventQueue = new ArrayList<>();
    (2)是否正在发送
    boolean isPosting;
    (3)是否主线程
    boolean isMainThread;
    (4)订阅者和订阅方法的封装类
    Subscription subscription;
    (5)事件
    Object event;
    (6)是否取消了
    boolean canceled;
}
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
    Class<?> eventClass = event.getClass();
    boolean subscriptionFound = false;
    if (eventInheritance) {
        (1)寻找订阅事件所有父类和接口
        List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
        int countTypes = eventTypes.size();
        for (int h = 0; h < countTypes; h++) {
            Class<?> clazz = eventTypes.get(h);
            (2)看下这个方法postSingleEventForEventType
            subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
        }
    } else {
        subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
    }
    (3)没有找到订阅者
    if (!subscriptionFound) {
        if (logNoSubscriberMessages) {
            logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
        }
        if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                eventClass != SubscriberExceptionEvent.class) {
            post(new NoSubscriberEvent(this, event));
        }
    }
}

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
    CopyOnWriteArrayList<Subscription> subscriptions;
    synchronized (this) {
        (1)找到所有订阅者
        subscriptions = subscriptionsByEventType.get(eventClass);
    }
        (2)遍历分发事件
    if (subscriptions != null && !subscriptions.isEmpty()) {
        for (Subscription subscription : subscriptions) {
            postingState.event = event;
            postingState.subscription = subscription;
            boolean aborted;
            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;
}

粘性事件发送
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);
}

发送事件总结:

  1. 从ThreadLocal获取当前线程的事件发送的封装类。
  2. 将事件添加到封装类的队列里面。
  3. 依次分发队列里面的所有事件。

特别注意

  1. 默认会分发事件的所有父类和接口和接口的父接口。

参考: