EventBus源碼全流程解讀

目錄

  • EventBus優(yōu)缺點(diǎn)

  • EventBus基本用法

  • EventBus源碼解析

一、EventBus優(yōu)缺點(diǎn)對(duì)比

優(yōu)點(diǎn):
1、是一個(gè)輕量級(jí)的事件總線,使用方便
2、去除應(yīng)用中大量的回調(diào),能一定程度解耦各組件

缺點(diǎn):
1、代碼可讀性降低,大量的事件使代碼解耦的同時(shí),聯(lián)系也變得弱了
2、不支持跨進(jìn)程通訊(廣播支持)

二、EventBus使用

首先使用別人家的東西第一步導(dǎo)包:

implementation 'org.greenrobot:eventbus:3.1.1'

EventBus使用相對(duì)簡(jiǎn)單,github下面就有使用步驟,我們直接參照


EventBus官方使用步驟說(shuō)明.png

1.定義傳遞的時(shí)間對(duì)象,該對(duì)象就是步驟2中接收的對(duì)象,也是步驟3中發(fā)送的事件
2.(1)定義接收事件方法(即訂閱方法),該方法用注解@Subscribe修飾,并通過(guò)threadMode指定其分發(fā)到的線程 (2)在定義接收方法的類(lèi)中(Android中一般為activity、fragment或service)注冊(cè)與解注冊(cè)EventBus
3.在任何地方通過(guò)post方法發(fā)送你的事件
通過(guò)以上三個(gè)步驟就可以使用EventBus進(jìn)行事件傳遞

三、源碼分析

在分析源碼之前我們有幾個(gè)問(wèn)題需要拋出
1、EventBus是如何確定哪些方法是訂閱方法的
2、EventBus是如何做線程切換的
3、EventBus為什么不支持跨進(jìn)程
如果讀完這篇源碼分析能解決以上問(wèn)題就足夠了

1.EventBus對(duì)象

EventBus.java

static volatile EventBus defaultInstance;
//雙重檢查鎖獲取單例對(duì)象
public static EventBus getDefault() {
        EventBus instance = defaultInstance;
        if (instance == null) {
            synchronized (EventBus.class) {
                instance = EventBus.defaultInstance;
                if (instance == null) {
                    instance = EventBus.defaultInstance = new EventBus();
                }
            }
        }
        return instance;
    }

EventBus.getDefault()通過(guò)雙重檢查鎖獲取單例對(duì)象,并通過(guò)volatile關(guān)鍵字保證單例對(duì)象的可見(jiàn)性

2.register與unregister

(1) 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();
        //1、SubscriberMethod為已訂閱的方法,這里通過(guò)類(lèi)對(duì)象查找到該類(lèi)所有訂閱方法  
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        //2、遍歷該類(lèi)所有已訂閱方法,并訂閱  
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

上面代碼也很好理解,
(1)根據(jù)類(lèi)對(duì)象獲得該類(lèi)中定義的訂閱方法信息
(2)遍歷所有訂閱方法執(zhí)行訂閱
下面針對(duì)這兩個(gè)問(wèn)題我們具體進(jìn)去看看
SubscriberMethodFinder.java

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }
        //核心代碼就是這一個(gè)判斷
        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;
        }
    }

這里主要根據(jù)ignoreGeneratedIndex標(biāo)志位判斷調(diào)用哪個(gè)方法獲取訂閱方法,ignoreGeneratedIndex標(biāo)志位使用的是EventBusBuilder的默認(rèn)實(shí)例,EventBusBuilder的ignoreGeneratedIndex默認(rèn)為false,因此這里會(huì)執(zhí)行findUsingInfo(subscriberClass)

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        //1、循環(huán)遍歷該類(lèi)及其父類(lèi)的方法
        while (findState.clazz != null) {
            //獲取已訂閱信息緩存
            findState.subscriberInfo = getSubscriberInfo(findState);
            //2、判斷訂閱方法是否為空,為空通過(guò)反射獲取訂閱方法;不為空直接使用緩存
            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);
    }

這里通過(guò)FindState對(duì)象保存需要的信息,通過(guò)遍歷該類(lèi)及其所有父類(lèi)獲取所有訂閱方法,訂閱信息如已存在于緩存中,直接取出使用;如果為緩存中沒(méi)有,使用反射獲取。下面我們著重看看反射獲取訂閱方法的相關(guān)內(nèi)容

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) {
            //1、判斷方法必須是public修飾,且不是static也不是abstract修飾的
            int modifiers = method.getModifiers();
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                //2、獲取方法入?yún)?,判斷入?yún)⒅挥幸粋€(gè),繼續(xù)執(zhí)行(表示訂閱方法只能有一個(gè)入?yún)ⅲ?                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 1) {
                    //3、獲取注解,判斷注解不為空則繼續(xù)執(zhí)行(表示訂閱方法必須由Subscribe注解)
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                    if (subscribeAnnotation != null) {
                        Class<?> eventType = parameterTypes[0];
                        if (findState.checkAdd(method, eventType)) {
                            //獲取直接中threadMode參數(shù),該參數(shù)為訂閱方法執(zhí)行的線程定義
                            ThreadMode threadMode = subscribeAnnotation.threadMode();
                            //4、以上全部符合要求,將信息保存到findState中
                            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");
            }
        }
    }

通過(guò)findUsingReflectionInSingleClass方法我們可以看到EventBus對(duì)訂閱方法的約束:
1、訂閱方法必須是public修飾的,且不能用static、abstract修飾
2、訂閱方法的參數(shù)只能是一個(gè),即事件對(duì)象
3、訂閱方法必須有@ Subscribe注解 ,threadMode默認(rèn)為POSTING

分析完訂閱方法的獲取,我們具體看看這些方法是如何訂閱的

    //根據(jù)事件類(lèi)型(eventType),保存所有eventType的訂閱方法
    private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
    //根據(jù)訂閱對(duì)象(subscriber),保存該訂閱對(duì)象的所有事件
    private final Map<Object, List<Class<?>>> typesBySubscriber;
    // Must be called in synchronized block
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        //訂閱方法的封裝對(duì)象
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        //將所有事件類(lèi)型的訂閱方法保存在一個(gè)集合中
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        /**
         *  1、判斷該事件是否已有存儲(chǔ)訂閱方法信息的容器;
         *  沒(méi)有則創(chuàng)建容器,并將容器存入subscriptionsByEventType中;
         *  若存在判斷該訂閱方法(newSubscription)是否已在容器中,已在拋出重復(fù)注冊(cè)異常
         */
        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();
        //2、根據(jù)優(yōu)先級(jí)將訂閱方法(newSubscription)插入容器對(duì)用的位置
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                subscriptions.add(i, newSubscription);
                break;
            }
        }
        //3、根據(jù)注冊(cè)對(duì)象subscriber保存該對(duì)象所有事件(實(shí)際subscribedEvents緩存的信息代表該注冊(cè)對(duì)象subscriber是否被注冊(cè))
        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);
            }
        }
    }

subscribe方法總共有做了幾件事:
1、通過(guò)eventType將該eventType下所有訂閱方法保存在subscriptionsByEventType中
2、通過(guò)訂閱對(duì)象將該訂閱對(duì)象所擁有的所有eventType對(duì)象保存在typesBySubscriber中
3、判斷是否是粘性事件并做對(duì)應(yīng)的處理(這里我們不做分析)

看到這里肯定有很多的疑惑:
1、subscriptionsByEventType這個(gè)map是做什么的?
2、typesBySubscriber這個(gè)map又是做什么的?
這里我們先揭曉答案:
1、subscriptionsByEventType實(shí)際是通過(guò)eventType保存該eventType所有的訂閱方法,這里理解為實(shí)際的訂閱;待事件分發(fā)時(shí)再根據(jù)eventType從subscriptionsByEventType中獲取訂閱方法進(jìn)行分發(fā)(后面post中會(huì)分析)
2、typesBySubscriber通過(guò)注冊(cè)對(duì)象保存該注冊(cè)對(duì)象所有的事件;這里保存代表為實(shí)際注冊(cè),待解注冊(cè)時(shí),再講該注冊(cè)對(duì)象的eventType從typesBySubscriber中移除,這個(gè)在unregister中可以體現(xiàn)

(2) unregister
接下來(lái)我們就來(lái)看看unregister方法:

/** Unregisters the given subscriber from all event classes. */
    public synchronized void unregister(Object subscriber) {
        //1、獲取緩存中注冊(cè)對(duì)象所有事件類(lèi)型,遍歷并解訂閱事件
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                unsubscribeByEventType(subscriber, eventType);
            }
            //全部事件解訂閱后,刪除typesBySubscriber中的類(lèi)對(duì)象,實(shí)際這里表示解注冊(cè)
            typesBySubscriber.remove(subscriber);
        } else {
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }

分析代碼可以知道,解注冊(cè)實(shí)際做了兩件事
1、解訂閱所有的訂閱事件,及遍歷執(zhí)行unsubscribeByEventType()方法
2、訂閱類(lèi)移除map列表中,即typesBySubscriber.remove(subscriber)
unsubscribeByEventType()方法通過(guò)名稱(chēng)已經(jīng)很明顯;無(wú)非就是將注冊(cè)時(shí)保存在subscriptionsByEventType中的訂閱方法移除;具體代碼貼出,但并沒(méi)有太值得閱讀的地方

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

3.post方法

剛剛已經(jīng)分析register方法,發(fā)現(xiàn)register其實(shí)最主要的就是將所有已注冊(cè)對(duì)象中的訂閱方法保存在subscriptionsByEventType這個(gè)map中,那post自然就是遍歷subscriptionsByEventType這個(gè)map然后執(zhí)行對(duì)應(yīng)的分發(fā)。

private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
        @Override
        protected PostingThreadState initialValue() {
            return new PostingThreadState();
        }
    };
    /** Posts the given event to the event bus. */
    public void post(Object event) {
        //1、使用ThreadLocal獲取當(dāng)前線程參數(shù)
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        //將事件加入List隊(duì)列中
        eventQueue.add(event);
        //2、判斷當(dāng)前線程post狀態(tài)
        if (!postingState.isPosting) {
            postingState.isMainThread = isMainThread();
            postingState.isPosting = true;
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                //3、postSingleEvent處理單個(gè)事件
                while (!eventQueue.isEmpty()) {
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                //4、恢復(fù)post線程狀態(tài)
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

這段代碼主要是判斷當(dāng)前線程post狀態(tài),如果有正在分發(fā)中的事件,則將新事件置入事件池排隊(duì)等待執(zhí)行;如果沒(méi)有,則將事件加入隊(duì)列并執(zhí)行。其核心代碼為postSingleEvent(eventQueue.remove(0), postingState) 所以我們繼續(xù)看看postSingleEvent做了些什么事

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;//該屬性判斷是否存在待分發(fā)事件的訂閱方法
        if (eventInheritance) {//eventInheritance為默認(rèn)Builder中的值,默認(rèn)為true
            //找到當(dāng)前待分發(fā)事件的所有事件類(lèi)型(這里包括父類(lèi)、接口類(lèi)等)
            List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
            int countTypes = eventTypes.size();
            for (int h = 0; h < countTypes; h++) {
                Class<?> clazz = eventTypes.get(h);
                //1、postSingleEventForEventType通過(guò)事件類(lèi)型查找是否有對(duì)應(yīng)的訂閱方法
                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
            }
        } else {
            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
        }
        //2、如果沒(méi)有找到對(duì)應(yīng)的訂閱方法,發(fā)送一個(gè)默認(rèn)事件
        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));
            }
        }
    }

1、判斷是否找到待分發(fā)事件的訂閱方法,找到則分發(fā)事件,其核心代碼為subscriptionFound |= postSingleEventForEventType(event, postingState, clazz)
2、未找到則默認(rèn)發(fā)送一個(gè)默認(rèn)的事件,post(new NoSubscriberEvent(this, event))

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            //1、在subscriptionsByEventType中獲取該事件對(duì)應(yīng)訂閱方法的集合
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            //2、遍歷集合,并執(zhí)行分發(fā)事件至具體的已訂閱方法中
            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;
    }

這里的主要邏輯如下
1、通過(guò)事件類(lèi)對(duì)象在subscriptionsByEventType這個(gè)map中取出該事件的所有訂閱類(lèi)集合,subscriptionsByEventType中的訂閱方法集合是在注冊(cè)是添加的,我們?cè)诜治鰎egister源碼時(shí)已經(jīng)分析了;
2、取出該事件訂閱方法合集之后就是遍歷所有的訂閱方法并分發(fā),該過(guò)程核心代碼為:postToSubscription(subscription, event, postingState.isMainThread)
說(shuō)了那么久才真正的進(jìn)入post最核心的地方--事件分發(fā),到目前為止我們知道post進(jìn)入時(shí)會(huì)根據(jù)當(dāng)前線程獲取一個(gè)緩存信息類(lèi)postingState對(duì)象,其不同線程有通的隊(duì)列處理消息分發(fā);但是我們都知道EventBus中是幫我們做了線程切換的,我們可以通過(guò)@ Subscribe注解的threadMode屬性指定訂閱方法執(zhí)行的線程;那這一塊的具體邏輯應(yīng)該就是在postToSubscription中,所以帶著問(wèn)題我們一起進(jìn)入看看:

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

進(jìn)入就可以看到代碼對(duì)threadMode進(jìn)行判斷:
PSOTING:直接反射調(diào)用訂閱方法;該模式表示在哪個(gè)線程發(fā)布事件就在哪個(gè)線程處理
MAIN:如果當(dāng)前post線程為主線程直接反射調(diào)用方法(防止主線程阻塞),如果post線程不是主線程,則調(diào)用mainThreadPoster排隊(duì)處理;該模式表示在主線程調(diào)用訂閱方法
MAIN_ORDERED:因?yàn)閙ainThreadPoster不會(huì)為null所以一直會(huì)排隊(duì)處理,并且會(huì)回調(diào)到主線程處理;該模式表示在主線程中排隊(duì)處理(即等待上一個(gè)時(shí)間處理后再發(fā)送下一個(gè)事件)
BACKGROUND:如果當(dāng)前post線程為主線程,開(kāi)啟一個(gè)新的后臺(tái)線程處理分發(fā),如果當(dāng)前post線程不為主線程,則直接反射調(diào)用;該模式表示事件一直在后臺(tái)線程中處理
ASYNC:由asyncPoster排隊(duì)處理;該模式表示不管post線程是否為主線程,都會(huì)新開(kāi)一個(gè)異步線程處理

這邊可以總結(jié)得出,部分情況直接反射調(diào)用訂閱方法;部分根據(jù)情況開(kāi)啟對(duì)應(yīng)的線程處理;如mainThreadPoster實(shí)際是Handler子類(lèi),通過(guò)handler機(jī)制切換回主線程,backgroundPoster、asyncPoster實(shí)際實(shí)現(xiàn)了Runable接口,在子線程中執(zhí)行;他們主要的工作只是線程切換,切換后最終都會(huì)通過(guò)EventBus的反射方法地調(diào)用訂閱方法 eventBus.invokeSubscriber(pendingPost)
反射方法如下:
其中帶一個(gè)入?yún)⒌姆瓷浞椒ň褪枪┚€程切換后調(diào)用的反射方法

/**
     * Invokes the subscriber if the subscriptions is still active. Skipping subscriptions prevents race conditions
     * between {@link #unregister(Object)} and event delivery. Otherwise the event might be delivered after the
     * subscriber unregistered. This is particularly important for main thread delivery and registrations bound to the
     * live cycle of an Activity or Fragment.
     */
    void invokeSubscriber(PendingPost pendingPost) {
        Object event = pendingPost.event;
        Subscription subscription = pendingPost.subscription;
        PendingPost.releasePendingPost(pendingPost);
        if (subscription.active) {
            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);
        }
    }

至此我們的源碼分析就結(jié)束了,現(xiàn)在讓我們回到開(kāi)始的那幾個(gè)問(wèn)題
1、EventBus是如何確定哪些方法是訂閱方法的
答:通過(guò)源碼分析知道,EventBus注冊(cè)是傳入一個(gè)類(lèi)對(duì)象,然后對(duì)類(lèi)對(duì)象的所有方法(包括其父類(lèi)的所有方法)進(jìn)行遍歷,然后根據(jù)一定的規(guī)則過(guò)濾訂閱方法,分析過(guò)程中已列出,可以重新查看SubscriberMethodFinder類(lèi)中的findUsingReflectionInSingleClass()方法;
2、EventBus是如何做線程切換的
答:通過(guò)Handler由子線程切換到主線程;通過(guò)實(shí)現(xiàn)Runable接口,切換至子線程處理,線程切換后通過(guò)反射調(diào)用訂閱方法分發(fā)事件
3、EventBus為什么不支持跨進(jìn)程
答:咋一看我們好像沒(méi)有再源碼中分析這一問(wèn)題,其實(shí)這是一個(gè)需要理解的問(wèn)題;首先我們需要理解Android的沙箱隔離機(jī)制,Android中為了各應(yīng)用的安全,不允許應(yīng)用直接訪問(wèn)其他應(yīng)用,所以Android中應(yīng)用通訊就需要另一個(gè)技術(shù)實(shí)現(xiàn)--IPC跨進(jìn)程通訊,我們回想下EventBus注冊(cè)時(shí)保存的訂閱方法的map集合,是保存在內(nèi)存中的,我們Post發(fā)送事件時(shí)也是直接在內(nèi)存中取出map中的方法,整個(gè)過(guò)程數(shù)據(jù)都涉及任何的IPC通訊。所以自然無(wú)法做到跨進(jìn)程調(diào)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容