EventBus 原理簡析

基於 eventbus:3.1.1 分析。

一.註解寫法

關鍵字是@Subscribe 

後面括號內可選參數是,threadMode表示可以選擇切換到哪個線程。sticky是否粘性事件,priority表示優先級。

ThreadMode: POSTING    表示發送事件的線程,當前線程。

ThreadMode: MAIN    表示UI線程

ThreadMode: MAIN_ORDERED    會先進入主線程隊列,然後主線程依次處理隊列消息

ThreadMode: BACKGROUND    當前線程是後臺線程則在當前線程處理,否則會丟到後臺線程池處理。

ThreadMode: ASYNC    同MAIN_ORDERED類似,會丟進後臺線程隊列,讓後臺線程池依次處理。

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

 

二.註冊與反註冊:

EventBus.getDefault().register(subscriber);
EventBus.getDefault().unregister(subscriber);

EventBus 的特點就是可以在任意類註冊,不像廣播一樣必須在有 context 的地方註冊。

日常使用,可以把這些放在父類裏,比如 BaseActivity 和 BaseFragment 這些。如果某個子類 Activity 根本沒有任何Subscriber註解導致報錯?沒關係 try catch 一下就行。

getDefault()方法就是獲取單例EventBus的單例,然後看 register 的調用流程,register 方法會把 this 這個當前類傳進去。

    public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

第三行看這名字,像是『找出所有 @Subscribe 標記的方法』,跟蹤一下看看怎麼實現的。

經過 findSubscriberMethods -> findUsingInfo -> findUsingReflectionInSingleClass (一般流程),我們到這個最後這個方法裏看看

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

可以看到第五行是Java知名的反射用法 java.lang.Class.getDeclaredMethod() 。通過它獲取到了類的所有方法,又在for循環下,使用一大堆代碼中篩選出了我們想要的。可以看到條件包括以下幾個條件,Public方法、非abstract或static等方法、方法的參數只有1個、使用了Subscribe註解。篩選後就得到我們想要的方法了,接着把以下這些信息『方法名 參數類型  註解上寫的線程類型  註解上寫的優先級  註解上寫的是否粘性事件』一個打包放到一個叫 SubscriberMethod 類實例中。

注意在 findUsingInfo 中有不斷向上遍歷父類的操作。所以這個EventBus的註冊操作是可以繼承的。

然後回到 register 方法,我們看到緊接着就是對這堆 SubscriberMethod 執行了 subscribe 方法。

首先 EventBus 庫有一個類叫 Subscription,兩個成員 subscriber 和 subscriberMethod。

final class Subscription {
    final Object subscriber;
    final SubscriberMethod subscriberMethod;
 ...
}

瞭解反射機制的話,讓容易知道如果我們有了包含在 SubscriberMethod 裏面的方法名、參數類型,又有了這個實例對象。就可以通過反射調用的該方法了。所以 Subscription 把這兩個捆綁在一個當做一個整體。

    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        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);

        ...
    }

subscribe 方法裏主要是把這次註冊的類實例和註解方法信息 放到 EventBus 這個控制中心的兩個成員變量裏面緩存着。

這兩個成員變量分別是CopyOnWriteArrayList<Subscription>> subscriptionsByEventType 和 Map<Object, List<Class<?>>> typesBySubscriber。

在對 subscriptionsByEventType 的 Value List<Subscription> 進行添加的時候,會根據優先級插入到指定順序。這樣 Subscriber 方法被調用的時候就可以根據設置的優先級來處理了。

畫個圖展示一下內部結構就是。

註冊流程就到此爲止了,下面講講反註冊流程。調用的是 unregister 這個方法。

    public synchronized void unregister(Object subscriber) {
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                unsubscribeByEventType(subscriber, eventType);
            }
            typesBySubscriber.remove(subscriber);
        } else {
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }

    /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
    private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
        List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions != null) {
            int size = subscriptions.size();
            for (int i = 0; i < size; i++) {
                Subscription subscription = subscriptions.get(i);
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }

這下子對應起上面那兩個Map的內部結構圖,就很容易看懂了。

先通過 unregister(this) 傳進來的 this 實例,在 typesBySubscriber 這個 Map 裏面找到這個類實例的所有 Event 類型。然後刪除 Subscription 裏面,調用者 subscriber == this 的,最後在 typesBySubscriber 把對應的 Map.Entry 刪掉。

 

 

三.發送事件 和 處理事件:

執行的代碼是 EventBus.getDefault().post(new XXEvent())

    /** 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 = isMainThread();
            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;
            }
        }
    }

    private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) {
            List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
            int countTypes = eventTypes.size();
            for (int h = 0; h < countTypes; h++) {
                Class<?> clazz = eventTypes.get(h);
                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
            }
        } else {
            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
        }
        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) {
            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;
    }

有一點有趣的是,postSingleEvent 方法裏會判斷一個屬性 eventInheritance,看是否向上查找它的父類。然後搜了下代碼,這個 eventInheritance 默認是爲true的。讓我學會了一個小技巧就是發送的 Event 有繼承關係也是可以觸達的。

在 postSingleEventForEventType 裏,通過 subscriptionsByEventType 這個 Map 類型的屬性,找到了這個事件的所有 Subscription。然後就是遍歷這堆 Subscription,逐個執行 postToSubscription 方法,由於涉及到線程調度,所以需要傳遞一個 postingState.isMainThread 信息。

接下來就是處理事件了

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

根據 Subscription 裏面帶有的 threadMode 屬性,結合發送事件所處在的線程,會進入下面的5種case。本質還是分兩種情況,一種是直接在當前線程上處理,即直接調用 invokeSubscriber(subscription, event) 。一種是把事件入隊到主線程或後臺線程。

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

直接調用 invokeSubscriber(subscription, event) ,就是在這個方法裏,利用反射執行這個方法了。

對於另外一種入隊的操作。可以看到有類裏有3種 Poster。其中 mainThreadPoster 使用的其實是子類 HandlerPoster。

    private final Poster mainThreadPoster;
    private final BackgroundPoster backgroundPoster;
    private final AsyncPoster asyncPoster;

拿BackgroundPoster來舉例

final class BackgroundPoster implements Runnable, Poster {

    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) {
                eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }

}

這3個Poster都分別有一個 PendingPostQueue,看源碼可以知道這是隊列。裏面的結點是一個個的 PendingPost。PendingPost 包含了事件event,我們熟悉的 Subscription,和下一個結點 next。

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

}

PendingPost 使用一個靜態 List 做緩存,創建一個 PendingPost 會優先從這個 List 裏面拿出並賦值(沒有的話再考慮 new 一個)。刪除也是判斷如果沒超過1萬,則塞入緩存 List 中。

 

在 BackgroundPoster 的 enqueue 方法裏,會先通過 subscription 和 event 生成一個 PendingPost。然後會讓這個 Poster 的隊列,對剛生成的 PendingPost 進行入隊操作。接着是獲取 eventBus 的線程池 ExecutorService,讓線程池開始工作。在 EventBusBuilder 裏面可以看到,默認的線程池是 Executors.newCachedThreadPool(),也就是允許建立無限多線程的線程池。

但是需要注意的是,在 BackgroundPoster 裏其實只是拿出一個線程,在 run 方法裏通過 while 循環不斷拿出隊列裏的事件來執行。在AsyncPoster 裏纔是真正的,讓線程池放開手腳的,可以無限制的開啓新線程來執行。

run方法裏核心還是調用到 invokeSubscriber 這個方法,同樣利用反射執行到這個我們註解 @Subscriber 標記的方法。

 

對於主線程 HandlerPoster,是通過參數 Looper.getMainLooper() 創建出一個運行在主線程的 Handler,然後隨便發個空消息到這個 Handler,就可以在主線程上一樣的從隊列拿出事件來處理了。見如下 HandlerPoster裏面的源碼

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

到這裏,整個通用的流程講完了。

 

 

粘性事件

粘性事件就跟Android的粘性廣播一樣。允許在先發送事件,再進行註冊的情況下,也能順利接受到該事件。

發送粘性事件的代碼是這樣的 EventBus.getDefault().postSticky(new XXEvent())

    private final Map<Class<?>, Object> stickyEvents;

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

可以看到,粘性事件的發送,把事件保存在 stickyEvents 這個 Map 裏面。這個 Map 的Value是一個 Object 類型(而不是List類型)也說明了,粘性事件只會保存最後一個事件,並不是全部都存下來。

然後在之前講到的 subscribe 方法裏( register 的時候調用到),有這麼一段。

    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {

		...

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

會在開啓了 eventInheritance 的情況下, 通過 isAssignableFrom 判斷出有沒有哪個 Subscriber 訂閱了當前這個事件或者當前事件的超類事件。然後通過 checkPostStickyEventToSubscription -> postToSubscription 最終回到我們之前講到的處理事件的流程。

 

 

EventBusBuilder

通過這一次閱讀源碼,我也瞭解到了原來 EventBus 支持使用 EventBusBuilder 配置的。

public class EventBusBuilder {
    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

    boolean logSubscriberExceptions = true;
    boolean logNoSubscriberMessages = true;
    boolean sendSubscriberExceptionEvent = true;
    boolean sendNoSubscriberEvent = true;
    boolean throwSubscriberException;
    boolean eventInheritance = true;
    boolean ignoreGeneratedIndex;
    boolean strictMethodVerification;
    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
    List<Class<?>> skipMethodVerificationForClasses;
    List<SubscriberInfoIndex> subscriberInfoIndexes;
    Logger logger;
    MainThreadSupport mainThreadSupport;

    EventBusBuilder() {
    }

    /** Default: true */
    public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
        this.logSubscriberExceptions = logSubscriberExceptions;
        return this;
    }

    /** Default: true */
    public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
        this.logNoSubscriberMessages = logNoSubscriberMessages;
        return this;
    }

    /** Default: true */
    public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
        this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
        return this;
    }

    /** Default: true */
    public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
        this.sendNoSubscriberEvent = sendNoSubscriberEvent;
        return this;
    }

    /**
     * Fails if an subscriber throws an exception (default: false).
     * <p/>
     * Tip: Use this with BuildConfig.DEBUG to let the app crash in DEBUG mode (only). This way, you won't miss
     * exceptions during development.
     */
    public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
        this.throwSubscriberException = throwSubscriberException;
        return this;
    }

    /**
     * By default, EventBus considers the event class hierarchy (subscribers to super classes will be notified).
     * Switching this feature off will improve posting of events. For simple event classes extending Object directly,
     * we measured a speed up of 20% for event posting. For more complex event hierarchies, the speed up should be
     * >20%.
     * <p/>
     * However, keep in mind that event posting usually consumes just a small proportion of CPU time inside an app,
     * unless it is posting at high rates, e.g. hundreds/thousands of events per second.
     */
    public EventBusBuilder eventInheritance(boolean eventInheritance) {
        this.eventInheritance = eventInheritance;
        return this;
    }


    /**
     * Provide a custom thread pool to EventBus used for async and background event delivery. This is an advanced
     * setting to that can break things: ensure the given ExecutorService won't get stuck to avoid undefined behavior.
     */
    public EventBusBuilder executorService(ExecutorService executorService) {
        this.executorService = executorService;
        return this;
    }

    /**
     * Method name verification is done for methods starting with onEvent to avoid typos; using this method you can
     * exclude subscriber classes from this check. Also disables checks for method modifiers (public, not static nor
     * abstract).
     */
    public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
        if (skipMethodVerificationForClasses == null) {
            skipMethodVerificationForClasses = new ArrayList<>();
        }
        skipMethodVerificationForClasses.add(clazz);
        return this;
    }

    /** Forces the use of reflection even if there's a generated index (default: false). */
    public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
        return this;
    }

    /** Enables strict method verification (default: false). */
    public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
        this.strictMethodVerification = strictMethodVerification;
        return this;
    }

    /** Adds an index generated by EventBus' annotation preprocessor. */
    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
        if (subscriberInfoIndexes == null) {
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }

    /**
     * Set a specific log handler for all EventBus logging.
     * <p/>
     * By default all logging is via {@link android.util.Log} but if you want to use EventBus
     * outside the Android environment then you will need to provide another log target.
     */
    public EventBusBuilder logger(Logger logger) {
        this.logger = logger;
        return this;
    }

比如說可以配置『繼承的時間是否起作用』,可以配置後臺線程池等操作。用法如下

EventBus myEventBus =
        EventBus.builder()
                .eventInheritance(false)
                .executorService(Executors
                .newSingleThreadExecutor())
                .build();

然後把這個 myEventBus 緩存起來,將來通過這個實例發送消息即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章