EventBus 3.1.1源碼分析

EventBus地址:https://github.com/greenrobot/EventBus

一谤狡、eventbus使用

EventBus是用于在Android和java中 發(fā)布/訂閱 的事件總線

模式圖

使用EventBus三部曲
1喳资、定義事件Event

public static class MessageEvent { /* Additional fields if needed */ }

2糕珊、聲明并注解一個(gè)訂閱者

@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {/* Do something */};

其中@Subscribe(threadMode = ThreadMode.MAIN)的threadMode 可以指定此方法運(yùn)行的線程模式贮折,threadMode = ThreadMode.MAIN運(yùn)行在UI線程,即onMessageEvent不能做耗時(shí)操作导街。

注冊(cè)和注銷訂閱者耻蛇,如果你是在做android開發(fā),那么應(yīng)該在activity/fragment的生命周期中進(jìn)行注冊(cè)/注銷朝蜘。

 @Override
 public void onStart() {
     super.onStart();
     EventBus.getDefault().register(this);
 }

 @Override
 public void onStop() {
     super.onStop();
     EventBus.getDefault().unregister(this);
 }

3恶迈、發(fā)布事件

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

二、分析EventBus源碼

1谱醇、EventBus的注冊(cè) EventBus.getDefault().register(this);

1-1暇仲、EventBus.getDefault()源碼

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

從源碼看,EventBus的getDefault()是采用的是單例模式枣抱,并且是線程安全熔吗,注意EventBus并不是一個(gè)嚴(yán)格意義上的單例模式,因?yàn)樗臉?gòu)造方法并不是私有的佳晶,所以你可以創(chuàng)建多個(gè)EventBus桅狠。
不了解單利模式可以看去之前寫的文章《設(shè)計(jì)模式—單例》
1-2、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);
            }
        }
    }

List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);

先看這句List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);從命名可以看出是對(duì)訂閱者方法的查找轿秧,并返回訂閱者方法集合中跌。再看下具體實(shí)現(xiàn)

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        // 先從緩存中取出subscriberMethods,如果有則直接返回METHOD_CACHE的value
        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;
        }
    }
  • List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);檢查Map中是否緩存了此訂閱者的方法集合菇篡,有直接返回漩符;
  • ignoreGeneratedIndex是個(gè)標(biāo)志位,true的情況下是通過(guò)反射來(lái)獲取訂閱者方法列表驱还,false下是在編譯期間生成SubscriberInfo嗜暴,然后在運(yùn)行時(shí)使用SubscriberInfo中保存的事件處理函數(shù)事件凸克,減少了反射的耗時(shí),會(huì)有運(yùn)行速度上的提升闷沥,默認(rèn)情況下ignoreGeneratedIndex值是false的
  • subscriberMethods = findUsingReflection(subscriberClass);看下源碼
    private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
            findUsingReflectionInSingleClass(findState);
            findState.moveToSuperclass(); // 移至父類
        }
        return getMethodsAndRelease(findState);
    }

> FindState findState = prepareFindState();

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

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

這里使用了緩存來(lái)避免對(duì)象的頻繁創(chuàng)建所帶來(lái)的開銷萎战,同時(shí)可以避免內(nèi)存抖動(dòng);注意這里使用synchronized來(lái)避免出現(xiàn)兩個(gè)或兩個(gè)以上線程操作同一個(gè)FindState對(duì)象舆逃。[這個(gè)技巧可以用于出來(lái)摸個(gè)對(duì)象的頻繁創(chuàng)建銷毀蚂维,及內(nèi)存抖動(dòng)激烈的問(wèn)題]
>> FindState

    static class FindState {
        // 訂閱者方法集合
        final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
        // event為key,method為value
        final Map<Class, Object> anyMethodByEventType = new HashMap<>();
        // 用method的名字生成一個(gè)method為key路狮,用訂閱者類為value
        final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
        final StringBuilder methodKeyBuilder = new StringBuilder(128);

        Class<?> subscriberClass;
        Class<?> clazz;
        // 跳過(guò)父類虫啥,默認(rèn)false-不跳過(guò)
        boolean skipSuperClasses;
        SubscriberInfo subscriberInfo;

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

        // 釋放資源,并恢復(fù)默認(rèn)設(shè)置
        void recycle() {
            subscriberMethods.clear();
            anyMethodByEventType.clear();
            subscriberClassByMethodKey.clear();
            methodKeyBuilder.setLength(0);
            subscriberClass = null;
            clazz = null;
            skipSuperClasses = false;
            subscriberInfo = null;
        }

        ......

        // 移至父類【給clazz賦值父類】
        // 如果clazz是java包和android包里的奄妨,賦值null涂籽,并結(jié)束
        void moveToSuperclass() {
            if (skipSuperClasses) {
                clazz = null;
            } else {
                clazz = clazz.getSuperclass();
                String clazzName = clazz.getName();
                /** Skip system classes, this just degrades performance. */
                if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
                    clazz = null;
                }
            }
        }
    }

主要說(shuō)明已經(jīng)放到注釋上。

        // 將滿足條件的方法及參數(shù)類型添加到anyMethodByEventType中
        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.
            // 這個(gè)涉及到兩層檢查
            // 第一層判斷有無(wú)method監(jiān)聽此eventType,如果沒(méi)有則可直接把找到的method加到subscriberMethods中展蒂。
            // 第二層判斷是方法簽名又活,這里的方法簽名其實(shí)是methodName+eventType
            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);
            }
        }
    
        // 方法簽名
        private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
            // 拼接所謂的方法簽名
            methodKeyBuilder.setLength(0);
            methodKeyBuilder.append(method.getName());
            methodKeyBuilder.append('>').append(eventType.getName());
    
            String methodKey = methodKeyBuilder.toString();
            Class<?> methodClass = method.getDeclaringClass(); // 獲得聲明此method的類
            Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
            // “methodClassOld.isAssignableFrom(methodClass)” methodClassOld是否是methodClass的父類或者同一個(gè)類
            if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
                // Only add if not already found in a sub class
                return true;
            } else {
                // Revert the put, old class is further down the class hierarchy
                subscriberClassByMethodKey.put(methodKey, methodClassOld);
                return false;
            }
        }
        

這兩個(gè)方法是FindState最重要的兩個(gè)方法,這里單獨(dú)舉例說(shuō)明下:
第一種情況:比如一個(gè)類有多個(gè)訂閱方法锰悼,方法名不同柳骄,但它們的參數(shù)類型都是相同的(雖然一般不這樣寫,但不排除這樣的可能)箕般,那么遍歷這些方法的時(shí)候耐薯,會(huì)多次調(diào)用到checkAdd方法,由于existing不為null丝里,那么會(huì)進(jìn)而調(diào)用checkAddWithMethodSignature方法曲初,但是由于每個(gè)方法的名字都不同,因此methodClassOld會(huì)一直為null杯聚,因此都會(huì)返回true臼婆。也就是說(shuō),允許一個(gè)類有多個(gè)參數(shù)相同的訂閱方法幌绍。
第二種情況:類B繼承自類A颁褂,而每個(gè)類都是有相同訂閱方法,換句話說(shuō)傀广,類B的訂閱方法繼承并重寫自類A颁独,它們都有著一樣的方法簽名。方法的遍歷會(huì)從子類開始伪冰,即B類誓酒,在checkAddWithMethodSignature方法中,methodClassOld為null贮聂,那么B類的訂閱方法會(huì)被添加到列表中靠柑。接著寨辩,向上找到類A的訂閱方法,由于methodClassOld不為null而且顯然類B不是類A的父類歼冰,methodClassOld.isAssignableFrom(methodClass)也會(huì)返回false捣染,那么會(huì)返回false。也就是說(shuō)停巷,子類繼承并重寫了父類的訂閱方法,那么只會(huì)把子類的訂閱方法添加到訂閱者列表榕栏,父類的方法會(huì)忽略畔勤。

>回到private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass),來(lái)看這個(gè)句findUsingReflectionInSingleClass(findState);

    private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;
        try {
            // This is faster than getMethods, especially when subscribers are fat classes like Activities
            // 獲取的是類【自身】聲明的所有方法扒磁,包含public庆揪、protected和private方法
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable th) {
            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
            // 獲取的是類的所有共有方法,**這就包括自身的所有【public】方法妨托,和從基類繼承的缸榛、從接口實(shí)現(xiàn)的所有public方法**
            methods = findState.clazz.getMethods();
            findState.skipSuperClasses = true;
        }
        for (Method method : methods) {
            int modifiers = method.getModifiers(); // 獲取字段的修飾符
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                // 獲得一個(gè)方法參數(shù)數(shù)組(getparameterTypes用于返回一個(gè)描述參數(shù)類型的Class對(duì)象數(shù)組)
                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();
                    // 不合法的注解方法 (方法只能有一個(gè)參數(shù))  
                    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();
                // 不合法的注解方法 (必須為public,非static兰伤、非abstract)  
                throw new EventBusException(methodName +
                        " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
            }
        }
    }

getDeclaredMethods()獲取的是類自身聲明的所有方法内颗,包含public、protected和private方法敦腔。

getMethods()獲取的是類的所有共有方法均澳,這就包括自身的所有public方法,和從基類繼承的符衔、從接口實(shí)現(xiàn)的所有public方法找前。而使用此方法自然不需要再遍歷父類的方法,所以findState.skipSuperClasses = true;來(lái)跳過(guò)父類的遍歷判族。

int modifiers = method.getModifiers();獲取字段的修飾符
對(duì)應(yīng)如下: PUBLIC: 1 PRIVATE: 2 PROTECTED: 4 STATIC: 8 FINAL: 16 SYNCHRONIZED: 32 VOLATILE: 64 TRANSIENT: 128 NATIVE: 256 INTERFACE: 512 ABSTRACT: 1024 STRICT: 2048

if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0)
private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;只獲取public類型的方法

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

當(dāng)方法參數(shù)個(gè)數(shù)為1躺盛,并且此方法有Subscribe類型的注解時(shí),通過(guò)findState.checkAdd(method, eventType)將方法和參數(shù)類型保存起來(lái)形帮,如果保存成功槽惫,則構(gòu)造一個(gè)SubscriberMethod對(duì)象把數(shù)據(jù)保存,并添加到findState.subscriberMethods集合中沃缘。

public class SubscriberMethod {
    final Method method; // 方法
    final ThreadMode threadMode; // 方法運(yùn)行線程類型
    final Class<?> eventType; // 參數(shù)類型
    final int priority; // 優(yōu)先級(jí)
    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;
    }

else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class))strictMethodVerification表示是否進(jìn)行精細(xì)檢查躯枢,默認(rèn)值是false。如果精細(xì)檢查【即strictMethodVerification=true】槐臀,并且method含有Subscribe對(duì)象的注解锄蹂,則拋出異常

  • subscriberMethods = findUsingInfo(subscriberClass);總算分析完了findUsingReflection,我們接著分析findUsingInfo水慨,先發(fā)下源碼
    private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
            // 獲取訂閱者信息得糜,沒(méi)有配置MyEventBusIndex返回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 {
                // 通過(guò)反射來(lái)查找訂閱方法
                findUsingReflectionInSingleClass(findState);
            }
            findState.moveToSuperclass();
        }
        return getMethodsAndRelease(findState);
    }
    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;
    }

> findState.subscriberInfo = getSubscriberInfo(findState);這里涉及到一個(gè)EventBus的高級(jí)用法敬扛,也就是通過(guò)注解在編譯期動(dòng)態(tài)生成一個(gè)MyEventBusIndex.java類,從而避免通過(guò)反射來(lái)查找滿足條件的方法朝抖。下面給出官方文檔及兩篇這個(gè)高級(jí)用法的文章:

官方總文檔地址:http://greenrobot.org/eventbus/documentation/
官方地址:https://github.com/greenrobot/EventBus
博客一:EventBus高級(jí)使用姿勢(shì)
博客二:EventBus3.0新特性之Subscriber Index

如果沒(méi)有配置這個(gè)高級(jí)用法啥箭,findState.subscriberInfo值便會(huì)是null,然后通過(guò)反射去獲取方法并篩選治宣。
MyEventBusIndex.java文件生成位置【我是用的是kotlin方案急侥,不同的方案位置會(huì)有小的區(qū)別,但大致位置都是在source下】

MyEventBusIndex文件位置.png

注意在匿名類中是用EventBus時(shí)侮邀,這種高級(jí)用法是不會(huì)在MyEventBusIndex.java生成相關(guān)信息的(原因請(qǐng)自行百度)坏怪,但會(huì)執(zhí)行反射的邏輯來(lái)完成對(duì)方法的篩選。

subscribe(subscriber, subscriberMethod);

再來(lái)分析下register(this);最后一句代碼subscribe(subscriber, subscriberMethod);绊茧,源碼如下

    // Must be called in synchronized block
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        // 從訂閱方法中拿到訂閱事件的類型  
        Class<?> eventType = subscriberMethod.eventType;
        // 創(chuàng)建一個(gè)新的訂閱
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        // 通過(guò)訂閱事件類型铝宵,找到所有的訂閱(Subscription),訂閱中包含了訂閱者,訂閱方法
        // CopyOnWriteArrayList是一個(gè)ArrayList的線程安全的變體华畏,具體原理鹏秋,使用請(qǐng)自行百度
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            // 如果該訂閱事件類型 沒(méi)有訂閱列表,那么創(chuàng)建一個(gè)該事件類型的訂閱列表
            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();
        // 根據(jù)訂閱方法的優(yōu)先級(jí)亡笑,添加到訂閱列表
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                subscriptions.add(i, newSubscription);
                break;
            }
        }
        
        // 將這個(gè)訂閱事件加入到訂閱者的訂閱事件列表中
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);

        if (subscriberMethod.sticky) {
            // eventInheritance=true時(shí)(默認(rèn)為true)
            // EventBus會(huì)考慮事件的超類侣夷,即事件如果繼承自超類,那么該超類也會(huì)作為事件發(fā)送給訂閱者仑乌。
            // 比如 A extends B implements C  發(fā)布者post(A),那么找訂閱者的時(shí)候不僅要找訂閱了事件A的訂閱者惜纸,還要找訂閱了B和C的訂閱者
            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();
                    // eventType是否是candidateEventType的父類或本身
                    if (eventType.isAssignableFrom(candidateEventType)) {
                        Object stickyEvent = entry.getValue();
                        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                    }
                }
            } else {
                Object stickyEvent = stickyEvents.get(eventType);
                checkPostStickyEventToSubscription(newSubscription, stickyEvent);
            }
        }
    }

> 大部分代碼的理解已放到代碼的注釋中了,這里我單獨(dú)拉出下面這段代碼分析下

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

先簡(jiǎn)單寫一個(gè)列子绝骚,方法講解

public class ClazzA {
    public ClazzA() { EventBus.getDefault().register(this); }     

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void eventbusMain(BaseEvent event) { }
}
public class BaseEvent { }
public class EventA extends BaseEvent { }

當(dāng)ClazzA構(gòu)造的時(shí)候會(huì)執(zhí)行EventBus的注冊(cè)流程耐版,又因?yàn)?code>ClazzA中的訂閱方法eventbusMainsticky所以會(huì)執(zhí)行subscribe(subscriber, subscriberMethod);方法中的subscriberMethod.sticky模塊內(nèi)代碼,而我們的EventBus是默認(rèn)構(gòu)造EventBus.getDefault(),也就是說(shuō)eventInheritancetrue會(huì)執(zhí)行eventInheritance代碼塊压汪,如果這個(gè)時(shí)候stickyEvents.entrySet()中有兩個(gè)Event事件對(duì)象 【a是EventA類型粪牲,b是BaseEvent類型】,通過(guò)for循環(huán)后止剖,這兩個(gè)對(duì)象都會(huì)交給eventbusMain(BaseEvent event)執(zhí)行腺阳,也就是說(shuō)eventType.isAssignableFrom(candidateEventType)這兩個(gè)對(duì)象都會(huì)通過(guò),【第一次循環(huán)穿香,BaseEvent是不是BaseEvent的父類或本身亭引? 第二次循環(huán),BaseEvent是不是ClazzA的父類或本身皮获?------ 因?yàn)?code>Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();是個(gè)集合焙蚓,順序是不確定,可能是反的,不要糾結(jié)】

  • checkPostStickyEventToSubscription(newSubscription, stickyEvent);發(fā)送訂閱事件類給訂閱者
    private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
        if (stickyEvent != null) {
            // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
            // --> Strange corner case, which we don't take care of here.
            postToSubscription(newSubscription, stickyEvent, isMainThread());
        }
    }
    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            case POSTING:
                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);
        }
    }
    void invokeSubscriber(Subscription subscription, Object event) {
        try {
            // 執(zhí)行訂閱方法
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (InvocationTargetException e) {
            handleSubscriberException(subscription, event, e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception", e);
        }
    }

ThreadMode 用法及說(shuō)明

  • PostThread:默認(rèn)的 ThreadMode购公,表示在執(zhí)行 Post 操作的線程直接調(diào)用訂閱者的事件響應(yīng)方法萌京,不論該線程是否為主線程(UI 線程)。當(dāng)該線程為主線程時(shí)宏浩,響應(yīng)方法中不能有耗時(shí)操作知残,否則有卡主線程的風(fēng)險(xiǎn)。適用場(chǎng)景:對(duì)于是否在主線程執(zhí)行無(wú)要求比庄,但若 Post 線程為主線程求妹,不能耗時(shí)的操作;
  • MainThread:在主線程中執(zhí)行響應(yīng)方法佳窑。如果發(fā)布線程就是主線程扒最,則直接調(diào)用訂閱者的事件響應(yīng)方法,否則通過(guò)主線程的 Handler 發(fā)送消息在主線程中處理——調(diào)用訂閱者的事件響應(yīng)函數(shù)华嘹。顯然,MainThread類的方法也不能有耗時(shí)操作法竞,以避免卡主線程耙厚。適用場(chǎng)景:必須在主線程執(zhí)行的操作;
  • BackgroundThread:在后臺(tái)線程中執(zhí)行響應(yīng)方法岔霸。如果發(fā)布線程不是主線程薛躬,則直接調(diào)用訂閱者的事件響應(yīng)函數(shù),否則啟動(dòng)唯一的后臺(tái)線程去處理呆细。由于后臺(tái)線程是唯一的型宝,當(dāng)事件超過(guò)一個(gè)的時(shí)候,它們會(huì)被放在隊(duì)列中依次執(zhí)行絮爷,因此該類響應(yīng)方法雖然沒(méi)有PostThread類和MainThread類方法對(duì)性能敏感趴酣,但最好不要有重度耗時(shí)的操作或太頻繁的輕度耗時(shí)操作,以造成其他操作等待坑夯。適用場(chǎng)景:操作輕微耗時(shí)且不會(huì)過(guò)于頻繁岖寞,即一般的耗時(shí)操作都可以放在這里;
  • Async:不論發(fā)布線程是否為主線程柜蜈,都使用一個(gè)空閑線程來(lái)處理仗谆。和BackgroundThread不同的是,Async類的所有線程是相互獨(dú)立的淑履,因此不會(huì)出現(xiàn)卡線程的問(wèn)題隶垮。適用場(chǎng)景:長(zhǎng)耗時(shí)操作,例如網(wǎng)絡(luò)訪問(wèn)秘噪。

mainThreadPoster.enqueue(subscription, event);主線程執(zhí)行訂閱方法狸吞。

private final Poster mainThreadPoster;

EventBus(EventBusBuilder builder) {
    ......
    mainThreadSupport = builder.getMainThreadSupport();
    mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
    ......
}
    MainThreadSupport getMainThreadSupport() {
        if (mainThreadSupport != null) {
            return mainThreadSupport;
        } else if (Logger.AndroidLogger.isAndroidLogAvailable()) {
            // android的Ui線程
            Object looperOrNull = getAndroidMainLooperOrNull();
            return looperOrNull == null ? null :
                    new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
        } else {
            return null;
        }
    }

其中Logger.AndroidLogger.isAndroidLogAvailable()其實(shí)是通過(guò)反射android中的"android.util.Log"包是否存在來(lái)實(shí)現(xiàn)的,代碼如下:

public interface Logger {

    ........
    public static class AndroidLogger implements Logger {
        static final boolean ANDROID_LOG_AVAILABLE;

        static {
            boolean android = false;
            try {
                android = Class.forName("android.util.Log") != null;
            } catch (ClassNotFoundException e) {
                // OK
            }
            ANDROID_LOG_AVAILABLE = android;
        }

        public static boolean isAndroidLogAvailable() {
            return ANDROID_LOG_AVAILABLE;
        }
       ........
    }
    .......
}

在靜態(tài)代碼塊中做的反射【只會(huì)執(zhí)行一次】,靜態(tài)代碼塊的知識(shí)偏離本文重點(diǎn)捷绒,請(qǐng)自行百度瑰排。

    Object getAndroidMainLooperOrNull() {
        try {
            // 獲得android主線程的looper
            return Looper.getMainLooper();
        } catch (RuntimeException e) {
            // Not really a functional Android (e.g. "Stub!" maven dependencies)
            return null;
        }
    }

這個(gè)方法是用來(lái)獲得android主線程的looper對(duì)象。

public interface MainThreadSupport {
    boolean isMainThread();
    Poster createPoster(EventBus eventBus);

    class AndroidHandlerMainThreadSupport implements MainThreadSupport {
        private final Looper looper;
        public AndroidHandlerMainThreadSupport(Looper looper) {
            this.looper = looper;
        }
        @Override
        public boolean isMainThread() {
            return looper == Looper.myLooper();
        }
        @Override
        public Poster createPoster(EventBus eventBus) {
            return new HandlerPoster(eventBus, looper, 10);
        }
    }
}
public class HandlerPoster extends Handler implements Poster {
    private final PendingPostQueue queue;
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    private boolean handlerActive;

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

    public void enqueue(Subscription subscription, Object event) {
        // 構(gòu)造一個(gè)post意圖對(duì)象
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            // 將構(gòu)造的PendingPost 加入到隊(duì)列中
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                // handler標(biāo)記為活躍狀態(tài)
                handlerActive = true;
                // 發(fā)送PendingPost對(duì)象
                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) {
                // 從隊(duì)列中獲得要執(zhí)行的PendingPost 
                PendingPost pendingPost = queue.poll();
                // 雙重加鎖檢查暖侨,如果隊(duì)列中沒(méi)有信息椭住,則hanlder狀態(tài)標(biāo)記為不活躍狀態(tài),同事退出循環(huán)
                if (pendingPost == null) {
                    synchronized (this) {
                        // Check again, this time in synchronized
                        pendingPost = queue.poll();
                        if (pendingPost == null) {
                            handlerActive = false;
                            return;
                        }
                    }
                }
                // 執(zhí)行訂閱者的訂閱方法
                eventBus.invokeSubscriber(pendingPost);
                // 循環(huán)發(fā)送隊(duì)列中的所有pendingPost對(duì)象
                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;
        }
    }
}

可以看出MainThreadSupport是通過(guò)主線程的Looper構(gòu)造一個(gè)主線程的handler對(duì)象字逗,這個(gè)handler中維護(hù)了一個(gè)隊(duì)列PendingPostQueue京郑,也就是說(shuō)mainThreadPoster.enqueue(subscription, event);是通過(guò)構(gòu)造PendingPost對(duì)象并添加到隊(duì)列中,然后激活隊(duì)列來(lái)實(shí)現(xiàn)發(fā)送葫掉。

backgroundPoster.enqueue(subscription, event);后臺(tái)線程中執(zhí)行響應(yīng)方法

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;
        }
    }
}
// 創(chuàng)建一個(gè)可緩存線程池些举,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程俭厚,若無(wú)可回收户魏,則新建線程。 
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

主要代碼就一句eventBus.getExecutorService().execute(this);交給線程池處理挪挤。

asyncPoster.enqueue(subscription, event);不論發(fā)布線程是否為主線程叼丑,都使用一個(gè)空閑線程來(lái)處理。和BackgroundThread不同的是扛门,Async類的所有線程是相互獨(dú)立的鸠信,因此不會(huì)出現(xiàn)卡線程的問(wèn)題。

class AsyncPoster implements Runnable, Poster {
    private final PendingPostQueue queue;
    private final EventBus eventBus;
    AsyncPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }
    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        queue.enqueue(pendingPost);
        eventBus.getExecutorService().execute(this);
    }
    @Override
    public void run() {
        PendingPost pendingPost = queue.poll();
        if(pendingPost == null) {
            throw new IllegalStateException("No pending post available");
        }
        eventBus.invokeSubscriber(pendingPost);
    }
}

AsyncPosterBackgroundPoster代碼基本一樣论寨,這里就不分析星立。它們兩個(gè)主要區(qū)別就是BackgroundPoster把一堆訂閱方法放在一個(gè)線程中執(zhí)行,而AsyncPoster是為每一個(gè)訂閱方法都創(chuàng)建一個(gè)線程來(lái)單獨(dú)執(zhí)行葬凳。

  • 總結(jié):到這終于分析完了EventBus的register()的整個(gè)流程绰垂。下面我繪制了一個(gè)流程圖來(lái)方便理解整個(gè)注冊(cè)流程。
    EventBus整個(gè)register流程

2火焰、EventBus的訂閱方法聲明

@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {/* Do something */};

2-1辕坝、訂閱方法說(shuō)明
在上面的EventBus.getDefault()流程分支中,我們得知EventBus的訂閱方法必須是public荐健,一個(gè)參數(shù)酱畅,并且要一定要有@Subscribe的注解,才能成功的將該方法添加到EventBus的訂閱方法列表中江场,同時(shí)EventBus提供了兩種方法來(lái)查找我們的訂閱方法纺酸,一種是反射【效率低】,另一種是通過(guò)注解址否,在編譯期動(dòng)態(tài)生成訂閱者方法列表【效率高】餐蔬。
2-2碎紊、Subscribe都有哪些注解參數(shù)

@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ù),分別是線程模式樊诺、是否粘性仗考、優(yōu)先級(jí)。

3词爬、EventBus發(fā)布事件EventBus.getDefault().post(new MessageEvent());

3-1秃嗜、void post(Object event)

    public void post(Object event) {
        // 獲得當(dāng)前線程的PostingThreadState封裝對(duì)象
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);
        
        if (!postingState.isPosting) {  // 為發(fā)送狀態(tài)
            postingState.isMainThread = isMainThread(); // 是否主線程
            postingState.isPosting = true; // 設(shè)置為正在發(fā)送狀態(tài)
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                while (!eventQueue.isEmpty()) {
                    postSingleEvent(eventQueue.remove(0), postingState); // 發(fā)送事件
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

第一行源碼是從currentPostingThreadState中獲取PostingThreadState對(duì)象,來(lái)下看currentPostingThreadState的定義

    private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
        @Override
        protected PostingThreadState initialValue() {
            return new PostingThreadState();
        }
    };

看來(lái)currentPostingThreadState是一個(gè)ThreadLocal<T>對(duì)象顿膨,ThreadLocal是一個(gè)線程內(nèi)部的數(shù)據(jù)存儲(chǔ)類锅锨,通過(guò)它可以在指定的線程中存儲(chǔ)數(shù)據(jù),而這段數(shù)據(jù)是不會(huì)與其他線程共享的恋沃”馗悖【下面是一段跑題代碼】

public class ThreadLocal<T> {
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }
}
// 其內(nèi)部原理是通過(guò)生成一個(gè)它包裹的泛型對(duì)象的數(shù)組,在不同的線程會(huì)有不同的數(shù)組索引值囊咏,
// 通過(guò)這樣就可以做到每個(gè)線程通過(guò) get() 方法獲取的時(shí)候恕洲,取到的只能是自己線程所對(duì)應(yīng)的數(shù)據(jù)。 

回到正題繼續(xù)分析

    /** For ThreadLocal, much faster to set (and get multiple values). */
    final static class PostingThreadState {
        final List<Object> eventQueue = new ArrayList<>();    // 事件隊(duì)列
        boolean isPosting;    // 是否在執(zhí)行postSingleEvent()方法
        boolean isMainThread;  // 是否是UI線程
        Subscription subscription;
        Object event;
        boolean canceled;
    }

PostingThreadState主要是封裝了一些post時(shí)的參數(shù)梅割。

post(Object event)的核心代碼就是這個(gè)句霜第,postSingleEvent(eventQueue.remove(0), postingState);

   private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) {
            // 獲取到eventClass所有父類的集合
            List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
            int countTypes = eventTypes.size();
            for (int h = 0; h < countTypes; h++) {
                Class<?> clazz = eventTypes.get(h);
                // 有一個(gè)為true,即真?zhèn)€運(yùn)算結(jié)果為true
                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
            }
        } else {
            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
        }
        if (!subscriptionFound) {
            // 沒(méi)有找到此事件類型的訂閱者邏輯
            if (logNoSubscriberMessages) {
                logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
            }
            // sendNoSubscriberEvent=true發(fā)送沒(méi)有此事件類型的訂閱者的事件
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }

List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);是用來(lái)獲取eventClass所繼承的父類炮捧,及所有接口。

    /** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */
    private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
        synchronized (eventTypesCache) {
            // eventTypesCache一個(gè)map的緩存對(duì)象惦银,通過(guò)緩存咆课,提高運(yùn)行效率
            List<Class<?>> eventTypes = eventTypesCache.get(eventClass);
            if (eventTypes == null) {
                eventTypes = new ArrayList<>();
                Class<?> clazz = eventClass;
                while (clazz != null) {
                    eventTypes.add(clazz);
                    addInterfaces(eventTypes, clazz.getInterfaces());
                    clazz = clazz.getSuperclass();
                }
                eventTypesCache.put(eventClass, eventTypes);
            }
            return eventTypes;
        }
    }
    /** Recurses through super interfaces. */
    //   遞歸方式查找出所有接口
    static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {
        for (Class<?> interfaceClass : interfaces) {
            if (!eventTypes.contains(interfaceClass)) {
                eventTypes.add(interfaceClass);
                addInterfaces(eventTypes, interfaceClass.getInterfaces());
            }
        }
    }

這里通過(guò)遞歸來(lái)查找出所有的接口,并添加到eventTypes中扯俱;

    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            // 所有訂閱了eventClass的事件集合
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted = false;
                try {
                    // 調(diào)用所有訂閱了此類型的书蚪,訂閱方法
                    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(subscription, event, postingState.isMainThread);上面register()中已有相關(guān)分析,這里不贅述了迅栅;

3-2殊校、void postSticky(Object event)

    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中读存,然后調(diào)用void post(Object event)为流,就和上面的分析一樣了,這里把event添加到stickyEvents目的是让簿,當(dāng)后續(xù)有register(this);時(shí)執(zhí)行sticky訂閱方法敬察。

4、EventBus的反注冊(cè) EventBus.getDefault().unregister(this);

1-1尔当、unregister(this)源碼

    /** Unregisters the given subscriber from all event classes. */
    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--;
                }
            }
        }
    }

unregister就是進(jìn)行一些數(shù)據(jù)從集合中移除莲祸,資源回收的操作和重置,看看就可以了。

PS:終于算分析完了锐帜,一貫只看不寫我的田盈,第一次寫這么長(zhǎng)的源碼分析文章,寫到最后自己都想放棄缴阎,但抱著做事要有始有終允瞧,還是堅(jiān)持寫完了@@@@@@~~~~~!R摺4墒健!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末语泽,一起剝皮案震驚了整個(gè)濱河市贸典,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌踱卵,老刑警劉巖廊驼,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異惋砂,居然都是意外死亡妒挎,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門西饵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)酝掩,“玉大人,你說(shuō)我怎么就攤上這事眷柔∑谙海” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵驯嘱,是天一觀的道長(zhǎng)镶苞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)鞠评,這世上最難降的妖魔是什么茂蚓? 我笑而不...
    開封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮剃幌,結(jié)果婚禮上聋涨,老公的妹妹穿的比我還像新娘。我一直安慰自己负乡,他們只是感情好牛郑,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著敬鬓,像睡著了一般淹朋。 火紅的嫁衣襯著肌膚如雪笙各。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天础芍,我揣著相機(jī)與錄音杈抢,去河邊找鬼。 笑死仑性,一個(gè)胖子當(dāng)著我的面吹牛惶楼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诊杆,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼歼捐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了晨汹?” 一聲冷哼從身側(cè)響起豹储,我...
    開封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淘这,沒(méi)想到半個(gè)月后剥扣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铝穷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年钠怯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片曙聂。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡晦炊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宁脊,到底是詐尸還是另有隱情断国,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布朦佩,位于F島的核電站并思,受9級(jí)特大地震影響庐氮,放射性物質(zhì)發(fā)生泄漏语稠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一弄砍、第九天 我趴在偏房一處隱蔽的房頂上張望仙畦。 院中可真熱鬧,春花似錦音婶、人聲如沸慨畸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)寸士。三九已至檐什,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弱卡,已是汗流浹背乃正。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留婶博,地道東北人瓮具。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凡人,于是被迫代替她去往敵國(guó)和親名党。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 我每周會(huì)寫一篇源代碼分析的文章,以后也可能會(huì)有其他主題.如果你喜歡我寫的文章的話,歡迎關(guān)注我的新浪微博@達(dá)達(dá)達(dá)達(dá)s...
    SkyKai閱讀 24,949評(píng)論 23 184
  • 原文鏈接:http://blog.csdn.net/u012810020/article/details/7005...
    tinyjoy閱讀 550評(píng)論 1 5
  • 對(duì)于Android開發(fā)老司機(jī)來(lái)說(shuō)肯定不會(huì)陌生挠轴,它是一個(gè)基于觀察者模式的事件發(fā)布/訂閱框架传睹,開發(fā)者可以通過(guò)極少的代碼...
    飛揚(yáng)小米閱讀 1,480評(píng)論 0 50
  • 最近在項(xiàng)目中使用了EventBus(3.0),覺得非常好用忠荞,于是就看了一些關(guān)于EventBus源碼分析的文章当窗,現(xiàn)在...
    shenhuniurou閱讀 1,508評(píng)論 0 4
  • 大腦思考時(shí)滚秩,同時(shí)發(fā)出一段聲接收一段音匹配一個(gè)概念,由此發(fā)現(xiàn)概念的聲音形態(tài)。這一刻浇辜,對(duì)稱邏輯呈現(xiàn),哲學(xué)隨之誕生从藤。
    JUNJKD閱讀 160評(píng)論 0 0