EventBus 是人們在日常開發(fā)中經(jīng)常會(huì)用到的開源庫,即使是不直接用的人,也多少借鑒過事件總線的用法。而且EventBus的代碼其實(shí)是非常簡單的,可以試著閱讀一下。

源碼閱讀系列不采用對(duì)功能進(jìn)行歸類的方法進(jìn)行閱讀,而是采用一個(gè)剛開始閱讀源碼的視角,從我們平時(shí)的API調(diào)用,一步步的去理解設(shè)計(jì)意圖和實(shí)現(xiàn)原理。

從這里開始

從這里開始吧,我們最常用的地方就是給一個(gè)函數(shù)添加上注解,我們先拋開apt生成的table,只看這個(gè)運(yùn)行時(shí)版本的訂閱設(shè)定。

// eventbus/Subscribe@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface Subscribe {    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).     */
    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! */
    int priority() default 0;
}

這個(gè)設(shè)定還是非常簡單的,而且都是我們熟悉的東西,線程類型(默認(rèn)的是拋出線程),是否是粘性事件,時(shí)間的優(yōu)先級(jí)。經(jīng)過這個(gè)類的出現(xiàn),我們就可以在類里面寫我們經(jīng)常寫的某個(gè)函數(shù)是訂閱函數(shù)了。

@Subscribe (...)public void getMessage(Event event) { ... }

下面的問題是我們改怎么讓EventBus找到這些方法呢?通過apt的版本我們知道這里面肯定有一個(gè)map或者是table的東西記錄了Object和Method之間的訂閱關(guān)系,而且還是一對(duì)多的。這個(gè)地方就是從每個(gè)我們進(jìn)行register的地方進(jìn)行的。

register & unregister

// eventbus/EventBus 
  /**     * 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);            }        }    }

我們在Activity/Fragment中都有可能會(huì)調(diào)用這個(gè)方法,如果是Fragment里面我們還會(huì)在onDestoryView()中進(jìn)行unregister(...)。在這段函數(shù)里我們發(fā)現(xiàn)使用反射從這個(gè)Class中找到了所有的訂閱者函數(shù)了,然后對(duì)每個(gè)訂閱者函數(shù)進(jìn)行注冊。

這里我們看看我們的SubribeMethod被包裝成了什么樣子:

/** Used internally by EventBus and generated subscriber indexes. */public class SubscriberMethod {    final Method method;    final ThreadMode threadMode;    final Class<?> eventType;    final int priority;    final boolean sticky;    /** Used for efficient comparison */
    String methodString;    public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {        this.method = method;        this.threadMode = threadMode;        this.eventType = eventType;        this.priority = priority;        this.sticky = sticky;
    }    @Override
    public boolean equals(Object other) {        if (other == this) {            return true;
        } else if (other instanceof SubscriberMethod) {            checkMethodString();
            SubscriberMethod otherSubscriberMethod = (SubscriberMethod)other;
            otherSubscriberMethod.checkMethodString();            // Don't use method.equals because of http://code.google.com/p/android/issues/detail?id=7811#c6
            return methodString.equals(otherSubscriberMethod.methodString);
        } else {            return false;
        }
    }    private synchronized void checkMethodString() {        if (methodString == null) {            // Method.toString has more overhead, just take relevant parts of the method
            StringBuilder builder = new StringBuilder(64);
            builder.append(method.getDeclaringClass().getName());
            builder.append('#').append(method.getName());
            builder.append('(').append(eventType.getName());
            methodString = builder.toString();
        }
    }    @Override
    public int hashCode() {        return method.hashCode();
    }
}

SubscribeMethod 攜帶了Method函數(shù)原型,還有就是我們在注解類里面提供的所有信息。還有一個(gè)Class<?>類型的EventType是指我們的事件類所對(duì)應(yīng)的Class,其余的方法都是為了比較和判斷是否相等來做的,equal/checkMethodString都是各種的拼字串來進(jìn)行存儲(chǔ)和判斷。

下面我們來看register里面調(diào)用的這段subscribe,這段非常的重要涉及了EventBus運(yùn)行時(shí)處理的絕大多數(shù)部分,還有就是粘性事件的分發(fā)。這段使用了大量的JDK的反射包的API,本身注釋也提醒我們了這段代碼需要加鎖,畢竟里面這一堆并發(fā)容器。所以我們最好先明確這段里面用的并發(fā)容器到底都是什么,這段代碼才好繼續(xù)看的下去。

    private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;    private final Map<Object, List<Class<?>>> typesBySubscriber;    private final Map<Class<?>, Object> stickyEvents;

主要的有這幾個(gè):

  1. 第一個(gè)Map存儲(chǔ)的Key是Class類型,Value是一個(gè)并發(fā)的ArrayList里面存的是對(duì)訂閱者和訂閱函數(shù)的一種綁定類Subscription從名字上也能看出Key是Event的Class對(duì)象。

  2. 第二個(gè)存儲(chǔ)的是訂閱者(Activity什么的?。┖虴vent類型的List。

  3. 第三個(gè)Map存儲(chǔ)的是粘性事件,Key是Event類型,Value是真實(shí)存在的StickyEvent對(duì)象。

知道這三個(gè)都是什么之后,這段代碼就好看了。我們來看前一部分。

// Must be called in synchronized block
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);      // Map<Class<?>, CopyOnWriteArrayList<Subscription>> 
        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;
            }
        }

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

這段寫的雖然有點(diǎn)亂套,但實(shí)際上寫的挺簡單的,而且一堆堆的O(n)遍歷,性能也就那樣(?)。

首先這里面出現(xiàn)了Subscription:

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;    Subscription(Object subscriber, SubscriberMethod subscriberMethod) {        this.subscriber = subscriber;        this.subscriberMethod = subscriberMethod;
        active = true;
    }    @Override
    public boolean equals(Object other) {        if (other instanceof Subscription) {
            Subscription otherSubscription = (Subscription) other;            return subscriber == otherSubscription.subscriber
                    && subscriberMethod.equals(otherSubscription.subscriberMethod);
        } else {            return false;
        }
    }    @Override
    public int hashCode() {        return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
    }
}

我們發(fā)現(xiàn)了這是訂閱者和訂閱方法類的一個(gè)契約關(guān)系類。

所以說上面subscribe函數(shù)主要做了,

  • 創(chuàng)建了訂閱者和方法類的綁定,然后存進(jìn)了subscriptionsByEventType

  • 對(duì)每個(gè)類型重新排列了一次優(yōu)先級(jí)

  • 對(duì)typesBySubscriber添加了對(duì)應(yīng)的類型

然后我們可以看一下這個(gè)函數(shù)的下一半,我們會(huì)驚奇地發(fā)現(xiàn),StickyEvent的發(fā)送時(shí)機(jī)居然是在register的時(shí)候:

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

這時(shí)候輪了一遍所有的粘性事件。isAssignableFrom類似于使用在Class之間的instance of 就是判斷兩個(gè)類是否有相同的接口關(guān)系,也就是說有繼承和實(shí)現(xiàn)關(guān)系的事件類,都會(huì)被判斷處理。

  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, Looper.getMainLooper() == Looper.myLooper());
        }
    }
 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 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);
        }
    }

之后就是針對(duì)各種的ThreadMode進(jìn)行了處理,同一線程的直接依賴Java的反射invoke執(zhí)行了,各種不可以的情況,比如說發(fā)到主線程但還沒在主線程的時(shí)候,都是用隊(duì)列進(jìn)行發(fā)送到對(duì)應(yīng)線程。

接下來我們看看這里面在各線程之間的發(fā)送是怎么實(shí)現(xiàn)的。

消息轉(zhuǎn)換線程

我們發(fā)現(xiàn)在Subscription和event入隊(duì)的時(shí)候我們把他們封裝成了一個(gè)PendingPost類:

// HandlePoster    void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);        synchronized (this) {
            queue.enqueue(pendingPost);            if (!handlerActive) {
                handlerActive = true;                if (!sendMessage(obtainMessage())) {                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

然后才進(jìn)行的入隊(duì)和發(fā)送,這個(gè)PendingPost就是一個(gè)帶有回收池的掩飾傳送類:

final class PendingPost {    private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();

    Object event;
    Subscription subscription;
    PendingPost next;    private PendingPost(Object event, Subscription subscription) {        this.event = event;        this.subscription = subscription;
    }    static PendingPost obtainPendingPost(Subscription subscription, Object event) {        synchronized (pendingPostPool) {            int size = pendingPostPool.size();            if (size > 0) {
                PendingPost pendingPost = pendingPostPool.remove(size - 1);
                pendingPost.event = event;
                pendingPost.subscription = subscription;
                pendingPost.next = null;                return pendingPost;
            }
        }        return new PendingPost(event, subscription);
    }    static void releasePendingPost(PendingPost pendingPost) {
        pendingPost.event = null;
        pendingPost.subscription = null;
        pendingPost.next = null;        synchronized (pendingPostPool) {            // Don't let the pool grow indefinitely
            if (pendingPostPool.size() < 10000) {
                pendingPostPool.add(pendingPost);
            }
        }
    }
}

這里的設(shè)計(jì)其實(shí)挺不錯(cuò)的,一個(gè)靜態(tài)的回收池,初始化靠一個(gè)靜態(tài)方法,優(yōu)先使用被回收的對(duì)象,實(shí)現(xiàn)和Message其實(shí)很像。另一個(gè)release方法就是把用完的對(duì)象回收起來。

PendingPostQueue 就是一個(gè)PendingPost的隊(duì)列,里面的操作基本上就是入隊(duì)出隊(duì)之類的,有點(diǎn)特殊的是入隊(duì)和出隊(duì)都有一把鎖。

接著這個(gè)隊(duì)列被用在了好幾個(gè)Poster類中,實(shí)現(xiàn)了向各個(gè)線程的消息轉(zhuǎn)換,首先我們來看向主線程發(fā)送數(shù)據(jù)的:

HandlePoster

final class HandlerPoster extends Handler {    private final PendingPostQueue queue;    private final int maxMillisInsideHandleMessage;    private final EventBus eventBus;    private boolean handlerActive;    HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {        super(looper);        this.eventBus = eventBus;        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
        queue = new PendingPostQueue();
    }    void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);        synchronized (this) {
            queue.enqueue(pendingPost);            if (!handlerActive) {
                handlerActive = true;                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();            while (true) {
                PendingPost pendingPost = queue.poll();                if (pendingPost == null) {                    synchronized (this) {                        // Check again, this time in synchronized
                        pendingPost = queue.poll();                        if (pendingPost == null) {
                            handlerActive = false;                            return;
                        }
                    }
                }
                eventBus.invokeSubscriber(pendingPost);                long timeInMethod = SystemClock.uptimeMillis() - started;                if (timeInMethod >= maxMillisInsideHandleMessage) {                    if (!sendMessage(obtainMessage())) {                        throw new EventBusException("Could not send handler message");
                    }
                    rescheduled = true;                    return;
                }
            }
        } finally {
            handlerActive = rescheduled;
        }
    }
}

HandlePoster 繼承自 Handler 再加上初始化的時(shí)候傳進(jìn)去的是Looper.getMainThread();所以能向主線程發(fā)送消息。每次入隊(duì)之后都會(huì)發(fā)送一條空消息去通知handleMessage函數(shù)處理隊(duì)列數(shù)據(jù),使用handlerActive作為控制標(biāo)記位。handleMessage是個(gè)死循環(huán)兩段的if判斷用來處理多線程的情況,invokeSubscriber的方式和之前類似。之后就是有一個(gè)閥值,當(dāng)時(shí)間超過10ms的時(shí)候就會(huì)發(fā)一個(gè)消息重入,并且退出這次循環(huán),這是防止時(shí)間太長阻塞主線程。

BackgroundPoster

final class BackgroundPoster implements Runnable {    private final PendingPostQueue queue;    private final EventBus eventBus;    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) {
                Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }
}

BackgroundPoster 自身是一個(gè)Runnable ,入隊(duì)之后就調(diào)用EventBus攜帶的一個(gè)線程池進(jìn)行運(yùn)行,同樣也是一個(gè)死循環(huán),用了一個(gè)生產(chǎn)者 vs 消費(fèi)者模式 進(jìn)行了有限等待,這1000ms內(nèi)入隊(duì)的消息都會(huì)被彈出處理。

    synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {        if (head == null) {            wait(maxMillisToWait);
        }        return poll();
    }

PendingPostQueue的poll(int)方法對(duì)隊(duì)列為空的情況進(jìn)行了等待,喚醒則出現(xiàn)在enqueue:

    synchronized void enqueue(PendingPost pendingPost) {        if (pendingPost == null) {            throw new NullPointerException("null cannot be enqueued");
        }        if (tail != null) {
            tail.next = pendingPost;
            tail = pendingPost;
        } else if (head == null) {
            head = tail = pendingPost;
        } else {            throw new IllegalStateException("Head present, but no tail");
        }        notifyAll(); // 在這進(jìn)行了喚醒
    }

AsyncPoster

如果說Background尚且能保證在同一個(gè)線程內(nèi)完成,AsyncPoster就完全進(jìn)行了異步操作。

class AsyncPoster implements Runnable {    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);
    }
}

這里面基本上什么都不控制,直接就來一個(gè)運(yùn)行一次,也不會(huì)有什么問題。。。

到這為止我們不但知道了方法是怎么注冊和綁定的,我們甚至還知道了粘性事件是怎么發(fā)送的了,接著我們來看方法查找和普通事件的發(fā)送是怎么進(jìn)行的。

方法查找

// package org.greenrobot.eventbus.meta;/** Base class for generated index classes created by annotation processing. */public interface SubscriberInfo {    // 獲取訂閱的類
    Class<?> getSubscriberClass();    // 所有的method
    SubscriberMethod[] getSubscriberMethods();    // 獲取父類的info
    SubscriberInfo getSuperSubscriberInfo();    // 是否檢查父類
    boolean shouldCheckSuperclass();
}

SubscriberInfo 描述了能通過注解類生成的Index的方法(具體功能我加了主食)。

/** * Interface for generated indexes. */public interface SubscriberInfoIndex {    SubscriberInfo getSubscriberInfo(Class<?> subscriberClass);
}

這個(gè)接口是查找info的。

另外可以說這其中的SubscriberMethodInfo存儲(chǔ)著SubscriberMethod所需的元信息:

public class SubscriberMethodInfo {    final String methodName;    final ThreadMode threadMode;    final Class<?> eventType;    final int priority;    final boolean sticky;
  ...

AbstractSubscriberInfo是一個(gè)抽象類,主要負(fù)責(zé)從Info創(chuàng)建出Method,又是一個(gè)反射:

    protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode,                                                      int priority, boolean sticky) {        try {
            Method method = subscriberClass.getDeclaredMethod(methodName, eventType);            return new SubscriberMethod(method, eventType, threadMode, priority, sticky);
        } catch (NoSuchMethodException e) {            throw new EventBusException("Could not find subscriber method in " + subscriberClass +                    ". Maybe a missing ProGuard rule?", e);
        }
    }

另外還有一個(gè)SimpleSubscriberInfo作為他的子類。

接下來的SubscriberMethodFinder也非常重要運(yùn)行時(shí)的方法查找都來自這里:

剛才我們在EventBus.register(...)中調(diào)用了這個(gè)函數(shù):

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);        if (subscriberMethods != null) {            return subscriberMethods;
        }        if (ignoreGeneratedIndex) {
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            subscriberMethods = findUsingInfo(subscriberClass);
        }        if (subscriberMethods.isEmpty()) {            throw new EventBusException("Subscriber " + subscriberClass
                    + " and its super classes have no public methods with the @Subscribe annotation");
        } else {
            METHOD_CACHE.put(subscriberClass, subscriberMethods);            return subscriberMethods;
        }
    }

其中的METHOD_CACHE是對(duì)每個(gè)類方法進(jìn)行緩存,防止多次查找,畢竟運(yùn)行時(shí)查找還是個(gè)復(fù)雜的操作,根據(jù)是否忽略生成Index。

private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);        while (findState.clazz != null) {            findUsingReflectionInSingleClass(findState);
            findState.moveToSuperclass();
        }        return getMethodsAndRelease(findState);
    }    private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;        try {            // This is faster than getMethods, especially when subscribers are fat classes like Activities
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable th) {            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
            methods = findState.clazz.getMethods();
            findState.skipSuperClasses = true;
        }        for (Method method : methods) {            int modifiers = method.getModifiers();            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                Class<?>[] parameterTypes = method.getParameterTypes();                if (parameterTypes.length == 1) {
                    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");
            }
        }
    }

findUsingReflectionInSingleClass對(duì)反射類進(jìn)行了處理,這里面通過掩模運(yùn)算檢查了訪問權(quán)限, 檢查了參數(shù)個(gè)數(shù)。

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

其中的checkAdd檢查了類型和方法簽名,每次輪轉(zhuǎn)完成之后都會(huì)進(jìn)行一次findState.moveToSuperclass();對(duì)父類進(jìn)行處理。

使用索引

因?yàn)榉瓷渌褂玫倪\(yùn)行時(shí)查找速度緩慢,所以我們也經(jīng)常會(huì)通過apt使用已經(jīng)創(chuàng)建好的Index。

剛才另一個(gè)分支的findUsingInfo就是使用已有的Index:

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);        while (findState.clazz != null) {
            findState.subscriberInfo = getSubscriberInfo(findState);            if (findState.subscriberInfo != null) {
                SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();                for (SubscriberMethod subscriberMethod : array) {                    if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                        findState.subscriberMethods.add(subscriberMethod);
                    }
                }
            } else {                findUsingReflectionInSingleClass(findState);
            }
            findState.moveToSuperclass();
        }        return getMethodsAndRelease(findState);
    }

這段非常簡單,幾乎就是剛才的驗(yàn)證而已,如果沒拿到數(shù)據(jù)的話,還會(huì)進(jìn)行正常的反射查找。

 // EventBusAnnotationProcessor 負(fù)責(zé)生成注解路由表
    private void createInfoIndexFile(String index) {
        BufferedWriter writer = null;        try {
            JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(index);            int period = index.lastIndexOf('.');
            String myPackage = period > 0 ? index.substring(0, period) : null;
            String clazz = index.substring(period + 1);
            writer = new BufferedWriter(sourceFile.openWriter());            if (myPackage != null) {
                writer.write("package " + myPackage + ";\n\n");
            }
            writer.write("import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;\n");
            writer.write("import org.greenrobot.eventbus.meta.SubscriberMethodInfo;\n");
            writer.write("import org.greenrobot.eventbus.meta.SubscriberInfo;\n");
            writer.write("import org.greenrobot.eventbus.meta.SubscriberInfoIndex;\n\n");
            writer.write("import org.greenrobot.eventbus.ThreadMode;\n\n");
            writer.write("import java.util.HashMap;\n");
            writer.write("import java.util.Map;\n\n");
            writer.write("/** This class is generated by EventBus, do not edit. */\n");
            writer.write("public class " + clazz + " implements SubscriberInfoIndex {\n");
            writer.write("    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;\n\n");
            writer.write("    static {\n");
            writer.write("        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();\n\n");            writeIndexLines(writer, myPackage);
            writer.write("    }\n\n");
            writer.write("    private static void putIndex(SubscriberInfo info) {\n");
            writer.write("        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);\n");
            writer.write("    }\n\n");
            writer.write("    @Override\n");
            writer.write("    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {\n");
            writer.write("        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);\n");
            writer.write("        if (info != null) {\n");
            writer.write("            return info;\n");
            writer.write("        } else {\n");
            writer.write("            return null;\n");
            writer.write("        }\n");
            writer.write("    }\n");
            writer.write("}\n");
        } catch (IOException e) {            throw new RuntimeException("Could not write source for " + index, e);
        } finally {            if (writer != null) {                try {
                    writer.close();
                } catch (IOException e) {                    //Silent
                }
            }
        }
    } private void writeIndexLines(BufferedWriter writer, String myPackage) throws IOException {        for (TypeElement subscriberTypeElement : methodsByClass.keySet()) {            if (classesToSkip.contains(subscriberTypeElement)) {                continue;
            }

            String subscriberClass = getClassString(subscriberTypeElement, myPackage);            if (isVisible(myPackage, subscriberTypeElement)) {                writeLine(writer, 2,                        "putIndex(new SimpleSubscriberInfo(" + subscriberClass + ".class,",                        "true,", "new SubscriberMethodInfo[] {");
                List<ExecutableElement> methods = methodsByClass.get(subscriberTypeElement);                writeCreateSubscriberMethods(writer, methods, "new SubscriberMethodInfo", myPackage);
                writer.write("        }));\n\n");
            } else {
                writer.write("        // Subscriber not visible to index: " + subscriberClass + "\n");
            }
        }
    }

有了這兩個(gè)方法之后我們就知道,平常的index就是通過這種方式拼接出來的。

Post消息

    /** 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;
            }
        }
    }

PostingThreadState是一個(gè)存儲(chǔ)在ThreadLocal中的對(duì)象,包含有以下各種內(nèi)容,線程信息,是否是主線程,是否取消,還有一個(gè)相應(yīng)的事件隊(duì)列。

  private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();        boolean subscriptionFound = false;        if (eventInheritance) {              /** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */
            List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);            int countTypes = eventTypes.size();            // 對(duì)所有的訂閱函數(shù),都調(diào)用發(fā)送數(shù)據(jù)
            for (int h = 0; h < countTypes; h++) {                // 所有的訂閱類
                Class<?> clazz = eventTypes.get(h);
                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
            }
        } else {          // 只發(fā)送一次
            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
        }        if (!subscriptionFound) {            if (logNoSubscriberMessages) {
                Log.d(TAG, "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) {
            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;
    }

之后對(duì)所有的訂閱類的所有訂閱者都發(fā)送一次數(shù)據(jù),發(fā)送數(shù)據(jù)方法和上文相同。

發(fā)送粘性數(shù)據(jù)就是拿鎖然后保存到隊(duì)列中去,這樣就可以在重新發(fā)送:

    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);
    }

因?yàn)槲覀儫o法確定什么時(shí)候粘性事件應(yīng)該停止繼續(xù)傳播,這取決于我們應(yīng)用的需要,所以我們應(yīng)當(dāng)手動(dòng)remove掉Sticky Event :

// 系統(tǒng)提供了如下方法
 public <T> T removeStickyEvent(Class<T> eventType) {        synchronized (stickyEvents) {            return eventType.cast(stickyEvents.remove(eventType));
        }
    }    public boolean removeStickyEvent(Object event) {        synchronized (stickyEvents) {
            Class<?> eventType = event.getClass();
            Object existingEvent = stickyEvents.get(eventType);            if (event.equals(existingEvent)) {
                stickyEvents.remove(eventType);                return true;
            } else {                return false;
            }
        }
    }    public void removeAllStickyEvents() {        synchronized (stickyEvents) {
            stickyEvents.clear();
        }
    }