1. 程式人生 > >android EventBus原始碼解析

android EventBus原始碼解析

尊重原創,轉載請標明出處   http://blog.csdn.net/abcdef314159

eventBus3.1.1

eventBus主要用於資料之間的傳遞,使用也非常簡單,就幾個主要的方法,一個是register和unregister,這兩個要成對出現,一般在onCreate中註冊,在onDestroy中取消註冊。還有幾個方法post,postSticky,removeAllStickyEvents。其中post必須在register之後才有效,否則接收不到資訊,postSticky可以在register之前和之後都可以。先看一下register方法

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

這裡面主要看一下findSubscriberMethods方法,他是找到你所在註冊類的註解方法,因為一般情況下要想接收資料,必須要加註解的方法,比如@Subscribe(threadMode = ThreadMode.MAIN)或者@Subscribe(threadMode = ThreadMode.MAIN, sticky = true),當然你也可以修改threadMode指定在其他執行緒中操作。
POSTING     :表示傳送事件和接收事件在相同的執行緒
MAIN        :表示在主執行緒中處理資料
MAIN_ORDERED:和MAIN一樣是在主執行緒中操作,但需要排隊
BACKGROUND  :在後臺執行緒中執行
ASYNC       :在另起一個非同步執行緒中執行

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

上面程式碼中ignoreGeneratedIndex預設情況下是false,其中findUsingReflection和findUsingInfo有可能最終呼叫的都是findUsingReflectionInSingleClass,為啥說是有可能,是因為findUsingInfo取值的時候會從先從subscriberInfoIndexes中取,如果有就返回,沒有就會呼叫findUsingReflectionInSingleClass方法,所以來看一下findUsingInfo方法

   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);
    }
注意這裡有個方法moveToSuperclass和上面的while迴圈,moveToSuperclass是獲取FindState欄位clazz的父類,就是在當前類中查詢之後還要在父類中查詢註解的方法,不斷往上找,直到父類為空為止。其中FindState是一個數據池FindState的物件,預設值為4,private static final int POOL_SIZE = 4;如果有就從池中取,沒有就建立,也是為了提高速度,看一下第一行程式碼prepareFindState
    private FindState prepareFindState() {
        synchronized (FIND_STATE_POOL) {
            for (int i = 0; i < POOL_SIZE; i++) {
                FindState state = FIND_STATE_POOL[i];
                if (state != null) {
                    FIND_STATE_POOL[i] = null;
                    return state;
                }
            }
        }
        return new FindState();
    }
來看一下上面的getSubscriberInfo方法,如果獲取為空,就會執行findUsingReflectionInSingleClass方法,來看一下getSubscriberInfo的具體實現
    private SubscriberInfo getSubscriberInfo(FindState findState) {
        if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
            SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
            if (findState.clazz == superclassInfo.getSubscriberClass()) {
                return superclassInfo;
            }
        }
        if (subscriberInfoIndexes != null) {
            for (SubscriberInfoIndex index : subscriberInfoIndexes) {
                SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
                if (info != null) {
                    return info;
                }
            }
        }
        return null;
    }
下面的subscriberInfoIndexes是由SubscriberMethodFinder的構造方法傳進來的值,這裡有一個官方提供的優化方法,就是從subscriberInfoIndexes中取,這個最後在介紹。我們先往上看,會發現無論是findUsingInfo還是findUsingReflection方法,在最後都會呼叫getMethodsAndRelease方法,我們再來看一下它的具體實現
    private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
        List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
        findState.recycle();
        synchronized (FIND_STATE_POOL) {
            for (int i = 0; i < POOL_SIZE; i++) {
                if (FIND_STATE_POOL[i] == null) {
                    FIND_STATE_POOL[i] = findState;
                    break;
                }
            }
        }
        return subscriberMethods;
    }
其實就相當於FindState的回收和訂閱方法的返回。下面再來看一下重量級方法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");
            }
        }
    }
通過反射的方式找到註解的方法,從上面程式碼可以看出,註解的方法只能有一個引數,其中checkAdd是根據方法和引數進行驗證。然後把找到的存到FindState中。OK,關於註解方法的查詢也就這些,下面看回過頭來看一下register發具體實現,在subscriberMethodFinder.findSubscriberMethods(subscriberClass)方法查詢之後,然後進行遍歷
    // Must be called in synchronized block
    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);

        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);
            }
        }
    }
程式碼比較簡單,這裡要記住一下subscriptionsByEventType欄位,為什麼在register之前post會收不到訊息,而在register之前postSticky確能收到訊息。因為這裡會把當前訂閱的方法存入到subscriptionsByEventType中,post的時候如果還沒有register,那麼subscriptionsByEventType就會為空,當然收不到訊息,而postSticky是粘性事件,會儲存在stickyEvents中,在register的時候還可以在觸發。看一下上面程式碼的第31行,如果之前傳送的是粘性事件,也就是postSticky,那麼這裡就會執行下面的checkPostStickyEventToSubscription方法。上面的boolean eventInheritance = true;預設值為true。checkPostStickyEventToSubscription方法會呼叫postToSubscription,來看一下postToSubscription方法
    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);
        }
    }
這裡就是上面說的幾種執行緒中的操作,看一下MAIN和MAIN_ORDERED。我們以MAIN執行緒為例繼續看,來看一下invokeSubscriber方法
    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);
        }
    }
這回是徹底明白了,找到訂閱的方法,然後通過反射進行呼叫。這裡只是在register中的呼叫,他只能呼叫sticky的事件。下面看一下最主要的兩個方法post和postSticky
    /**
     * Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky
     * event of an event's type is kept in memory for future access by subscribers using {@link Subscribe#sticky()}.
     */
    public void postSticky(Object event) {
        synchronized (stickyEvents) {
            stickyEvents.put(event.getClass(), event);
        }
        // Should be posted after it is putted, in case the subscriber wants to remove immediately
        post(event);
    }
我們看到postSticky呼叫了post,和post唯一的區別就是他儲存了event物件,儲存在stickyEvents中,所以postSticky的事件可以在register之前呼叫原理就在這,把當前訂閱的類儲存在stickyEvents中,然後register的時候就可以呼叫,而post沒有儲存,所以register的時候自然沒法觸發,這裡要注意在上面分析的subscribe方法中,我們知道他只能觸發sticky的事件,我們接著往下看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 = 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;
            }
        }
    }
這裡就不在過多介紹,主要看一下postSingleEvent方法
    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));
            }
        }
    }
接著看postSingleEventForEventType方法
    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;
    }
這裡我們先看一下postToSubscription,就是上面剛分析的,就不在說了,這裡我們來看一下subscriptionsByEventType,我們上面分析的subscriptionsByEventType是在register的時候才會把訂閱的事件儲存,如果在register之前呼叫post和postSticky方法,那麼這裡subscriptionsByEventType返回的自然是空,所以也就不會執行下面的程式碼了,但postSticky不同,雖然他不能執行,但它把訂閱的物件儲存在了stickyEvents中,在register的時候就會觸發了。下面再來說說上面遺留的問題,上面說道subscriberInfoIndexes中取值的時候的問題,這個欄位是在SubscriberMethodFinder構造方法中帶過來的,而SubscriberMethodFinder是在EventBus類的建構函式中初始化的,而EventBus的建構函式傳入的是EventBusBuilder,使用的是建造者模式,且subscriberInfoIndexes預設為空,我們看一下他傳值的方法
    /** Adds an index generated by EventBus' annotation preprocessor. */
    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
        if (subscriberInfoIndexes == null) {
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }
這個很簡單,實際上還可以使用一種更加高效的方法,自動為我們生成一個MyEventBusIndex類,它裡面會包含我們註解的方法。具體實現是在app的defaultConfig中新增下面程式碼
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [ eventBusIndex : 'com.example.myapp.MyEventBusIndex' ]
            }
        }
然後在dependencies中新增下面程式碼
    implementation 'org.greenrobot:eventbus:3.1.1'
    annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'

就會自動為我們生成一個類,具體位置如下,                      

       

這裡我寫了兩個類,每個類都寫了兩個註解的方法

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onReceiveEvent(String event) {
        Log.d("wld_____", "FirstActivity:onReceiveEvent1:" + event);
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onReceiveStickyEvent(String event) {
        Log.d("wld_____", "FirstActivity:onReceiveStickyEvent2:" + event);
    }
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onReceiveEvent(String event) {
        Log.d("wld_____", "SecondActivity:onReceiveEvent:" + event);
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onReceiveStickyEvent(String event) {
        Log.d("wld_____", "SecondActivity:onReceiveStickyEvent:" + event);
    }
我們來看一下生成的MyEventBusIndex類
package com.example.myapp;

import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberMethodInfo;
import org.greenrobot.eventbus.meta.SubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberInfoIndex;

import org.greenrobot.eventbus.ThreadMode;

import java.util.HashMap;
import java.util.Map;

/** This class is generated by EventBus, do not edit. */
public class MyEventBusIndex implements SubscriberInfoIndex {
    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;

    static {
        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();

        putIndex(new SimpleSubscriberInfo(yiquan.xianquan.com.myapplication.SecondActivity.class, true,
                new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onReceiveEvent", String.class, ThreadMode.MAIN),
            new SubscriberMethodInfo("onReceiveStickyEvent", String.class, ThreadMode.MAIN, 0, true),
        }));

        putIndex(new SimpleSubscriberInfo(yiquan.xianquan.com.myapplication.FirstActivity.class, true,
                new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onReceiveEvent", String.class, ThreadMode.MAIN),
            new SubscriberMethodInfo("onReceiveStickyEvent", String.class, ThreadMode.MAIN, 0, true),
        }));

    }

    private static void putIndex(SubscriberInfo info) {
        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
    }

    @Override
    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
        if (info != null) {
            return info;
        } else {
            return null;
        }
    }
}
至於他的使用,可以這樣
        EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
        EventBus eventBus = EventBus.getDefault();

這裡最好把EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();放到Application中,只初始化一次,如果多次初始化會直接拋異常,我們看一下原始碼

    /**
     * Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be
     * done only once before the first usage of the default EventBus.
     *
     * @throws EventBusException if there's already a default EventBus instance in place
     */
    public EventBus installDefaultEventBus() {
        synchronized (EventBus.class) {
            if (EventBus.defaultInstance != null) {
                throw new EventBusException("Default instance already exists." +
                        " It may be only set once before it's used the first time to ensure consistent behavior.");
            }
            EventBus.defaultInstance = build();
            return EventBus.defaultInstance;
        }
    }

所以他只能初始化一次。OK,EventBus的原理基本已經分析完畢,下面來看一下具體使用。下面有兩個類FirstActivity和SecondActivity,我們暫且標記為A和B

public class FirstActivity extends AppCompatActivity {
    private Button button1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
        EventBus.getDefault().register(this);
        button1 = findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                EventBus.getDefault().postSticky("111111");
                startActivity(new Intent(FirstActivity.this, SecondActivity.class));
            }
        });
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onReceiveEvent(String event) {
        Log.d("wld_____", "FirstActivity:onReceiveEvent:" + event);
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onReceiveStickyEvent(String event) {
        Log.d("wld_____", "FirstActivity:onReceiveStickyEvent:" + event);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
}
public class SecondActivity extends AppCompatActivity {
    private Button button2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        EventBus.getDefault().register(this);
        button2 = findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onReceiveEvent(String event) {
        Log.d("wld_____", "SecondActivity:onReceiveEvent:" + event);
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onReceiveStickyEvent(String event) {
        Log.d("wld_____", "SecondActivity:onReceiveStickyEvent:" + event);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
}

執行一下,看一下列印的log


結果顯然是正確的,因為在A和B中都是先註冊,所以會獲得他們註解的方法,當在A中傳送訊息的時候A的兩個方法都是可以接收到訊息的,但在B中由於B還沒有啟動,所以當B啟動的時候只能接收到sticky註冊的方法。改一下程式碼再看一下

                EventBus.getDefault().post("111111");
                startActivity(new Intent(FirstActivity.this, SecondActivity.class));
看一下列印log,


我們發現只有A的兩個方法執行了,B的方法一個也沒執行,這個也很好理解,因為B還沒有註冊就開始傳送訊息,所以收不到。再來改一下程式碼看看,調整一下順序

                startActivity(new Intent(FirstActivity.this, SecondActivity.class));
                EventBus.getDefault().post("111111");
看一下列印log


一樣B不會列印,這是因為Activity的啟動是耗時的,而B還沒啟動就開始傳送訊息,自然是接收不到的,我們再改一下,延遲30毫秒在傳送,30毫秒的時間Activity應該完全啟動了吧,我們看一下

                startActivity(new Intent(FirstActivity.this, SecondActivity.class));
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        EventBus.getDefault().post("111111");
                    }
                }, 30);
            }

再來看一下列印log


看到沒,A和B的兩個註解的方法都執行了,這是因為延遲之後A和B都已經啟動了,但A的onDestroy還沒有執行,所以兩個類的註解方法都會執行的。OK,到這裡EventBus的原理就已經分析完了。