EventBus原始碼解讀詳細註釋(5)事件訊息繼承性分析 eventInheritance含義

王世暉發表於2016-03-21

[EventBus原始碼分析(一):入口函式提綱挈領(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51802172)
[EventBus原始碼分析(二):register方法儲存事件的訂閱者列表(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51819508)
[EventBus原始碼分析(三):post方法釋出事件【獲取事件的所有訂閱者,反射呼叫訂閱者事件處理方法】(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51821143)
[EventBus原始碼分析(四):執行緒模型分析(2.4版本)](http://blog.csdn.net/wangshihui512/article/details/51832001)
[EventBus原始碼解讀詳細註釋(1)register的幕後黑手](http://blog.csdn.net/wangshihui512/article/details/50914817)
[EventBus原始碼解讀詳細註釋(2)MainThread執行緒模型分析](http://blog.csdn.net/wangshihui512/article/details/50934012)
[EventBus原始碼解讀詳細註釋(3)PostThread、MainThread、BackgroundThread、Async四種執行緒模式的區別](http://blog.csdn.net/wangshihui512/article/details/50935729)
[EventBus原始碼解讀詳細註釋(4)register時重新整理的兩個map](http://blog.csdn.net/wangshihui512/article/details/50938663)
[EventBus原始碼解讀詳細註釋(5)事件訊息繼承性分析 eventInheritance含義](http://blog.csdn.net/wangshihui512/article/details/50947102)
[EventBus原始碼解讀詳細註釋(6)從事件釋出到事件處理,究竟發生了什麼!](http://blog.csdn.net/wangshihui512/article/details/50949960)



如果post(A),A extends B implements C,D implements C

那麼onEvent(A)、onEvent(B)、onEvent(C)、onEvent(D)四個事件處理方法那些能得到呼叫呢

答案是onEvent(A)、onEvent(B)、onEvent(C)這三個

先用簡單的實驗驗證,然後原始碼分析

寫一個簡單的Activity測試

public class MainActivity extends Activity {
    private static final String TAG="EventBus";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    protected void onStart() {
        super.onStart();
        Log.v(TAG, "onStart()");
        EventBus.getDefault().register(this);
        EventBus.getDefault().post(new A());
    }
    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
        Log.v(TAG, "onStop()");
    }
    public void onEvent(A msg){
        Log.v(TAG, "onEvent(A msg)");
    }
    public void onEvent(B msg){
        Log.v(TAG,"onEvent(B msg)");
    }
    public void onEvent(C msg){
        Log.v(TAG,"onEvent(C msg)");
    }
    public void onEvent(D msg){
        Log.v(TAG,"onEvent(D msg)");
    }
}
其中 A、B、C、D的繼承關係如下:

public class A extends B implements C{}
public class B {}
public interface C {}
public class D implements  C{}
讓程式跑起來,看一下log怎麼說:

V/EventBus: onStart()
V/EventBus: onEvent(A msg)
V/EventBus: onEvent(C msg)
V/EventBus: onEvent(B msg)
V/EventBus: onStop()

由此可知EventBus中:

如果post(A),A extends B implements C,D implements C

那麼onEvent(A)、onEvent(B)、onEvent(C)會被呼叫,onEvent(D)不會被呼叫

接下來看看原始碼怎麼實現:

/*在此標誌位為true的前提下
如果post(A),A extends B implements C,D implements C
那麼onEvent(A)、onEvent(B)、onEvent(C)會被呼叫,onEvent(D)不會被呼叫*/
private final boolean eventInheritance;
這是一個成員屬性標誌位

釋出事件的時候呼叫的是post,post內部呼叫下邊這個方法

 private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        /*獲取事件的Class,所有事件的Class對應的訂閱者列表在register的時候是已經儲存了的*/
        Class<?> eventClass = event.getClass();
        /*根據事件的Class找到訂閱者的標誌狀態,初始化為false*/
        boolean subscriptionFound = false;
        /*
        * 比如 A extends B implements C  釋出者post(A),那麼找訂閱者的時候不僅要找訂閱了事件A的訂閱者
        * 還要找訂閱了B和C的訂閱者*/
        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) {
                Log.d(TAG, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }

前邊說過了EventBus維護了兩個重要的map。其中一個就是事件的Class到能處理此事件的所有訂閱者列表的map,因此不僅要把事件的Class存入map中的訂閱者列表,還要把事件的所有父類和所有實現的介面的Class存入訂閱者列表。下邊是找到某個類所有父類和所有實現介面的方法:

/** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */
    /*找到事件的所有父類和實現的介面,以Class列表的形式返回*/
    private List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
        /*private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<Class<?>, List<Class<?>>>();*/
        synchronized (eventTypesCache) {
            /*檢視快取,看能否命中*/
            List<Class<?>> eventTypes = eventTypesCache.get(eventClass);
            /*快取不命中*/
            if (eventTypes == null) {
                /*建立事件型別列表*/
                eventTypes = new ArrayList<Class<?>>();
                Class<?> clazz = eventClass;
                /*getSuperclass()返回null的情況:Class表示的類為Object、基本資料型別、介面或者void*/
                while (clazz != null) {
                    eventTypes.add(clazz);
                    /*把介面對應的Class也新增進Class列表
                    * clazz.getInterfaces():返回clazz表示的類直接實現的介面的Class列表,不包括間接實現的介面
                    * */
                    addInterfaces(eventTypes, clazz.getInterfaces());
                    /** public Class<? super T> getSuperclass() :
                     * Returns the Class object which represents the superclass of the
                     * class represented by this  Class. If this  Class represents
                     * the Object class, a primitive type, an interface or void then the
                     * method returns null. If this Class represents an array
                     * class then the  Object class is returned.
                     */

                    clazz = clazz.getSuperclass();
                }
                /*找到一個事件的所有父類和所有實現介面的Class挺複雜的,迴圈加遞迴的,還是加入快取機制提高效能吧*/
                eventTypesCache.put(eventClass, eventTypes);
            }
            return eventTypes;
        }
    }

    /** Recurses through super interfaces. 獲取某個類直接實現的所有介面,包括間接實現的
     * @param eventTypes
     * @param interfaces*/
    static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {
        /*對這個類直接實現的每個介面開始遍歷*/
        for (Class<?> interfaceClass : interfaces) {
            /*如果這個介面還沒有新增到列表接把他新增到列表*/
            if (!eventTypes.contains(interfaceClass)) {
                eventTypes.add(interfaceClass);
                /*把這個介面所直接實現的所有介面的Class也新增進列表 遞迴呼叫*/
                addInterfaces(eventTypes, interfaceClass.getInterfaces());
            }
        }
    }



相關文章