EventBus 源碼解讀

1、獲取單例實(shí)例:

public static EventBus getDefault() {
    // 叨叨兩句,雙重鎖機(jī)制 才是 單例創(chuàng)建的最佳姿勢
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}

2、調(diào)用 注冊方法

public void register(Object subscriber) {
    //獲取訂閱的當(dāng)前類
    Class<?> subscriberClass = subscriber.getClass();
    //獲取到當(dāng)前訂閱類中被@Subscribe 注解的方法
    // 先會從緩存中獲取,此處省略
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}
//  訂閱的時(shí)候會加入到 
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    // 事件類型
    Class<?> eventType = subscriberMethod.eventType;
    // 創(chuàng)建新的訂閱對象,用Subscription類包裝訂閱者以及訂閱方法
    Subscription newSubscription = new Subscription(subscriber,subscriberMethod);
    // 取出所有訂閱了該事件的Subscription集合
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    // 可能此eventType是第一次出現(xiàn),初始化一下
  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);
        }
    }
    // 優(yōu)先級重新排序下
    int size = subscriptions.size();
    for (int i = 0; i <= size; i++) {
      //  將新添加注解優(yōu)先級高的添加到集合中
        if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
            subscriptions.add(i, newSubscription);
            break;
        }
    }
    // 該訂閱者所有的關(guān)心的事件類型集合  比如:一個(gè)Activity 有多個(gè)事件,就會有多個(gè)觀察的實(shí)體Bean
    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    // 第一次先初始化
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    subscribedEvents.add(eventType);
// 如果當(dāng)前訂閱方法接受粘性事件,并且訂閱方法關(guān)心的事件在粘性事件集合中,那么將該event事件post給subscriber
    if (subscriberMethod.sticky) {
        if (eventInheritance) {
            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);
        }
    }
}

================至此,register 方法完成===========================
3、調(diào)用 post 方法:

 public void post(Object event) {
    PostingThreadState postingState = currentPostingThreadState.get();
  // 構(gòu)建了事件隊(duì)列
    List<Object> eventQueue = postingState.eventQueue;
  //  每post 一個(gè)事件進(jìn)來,就加入到事件隊(duì)列中
    eventQueue.add(event);
    if (!postingState.isPosting) {
        //判斷當(dāng)前線程是否是主線程
        postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
        postingState.isPosting = true;
        if (postingState.canceled) {
            throw new EventBusException("Internal error. Abort state was not reset");
        }
        try {
             // while 循環(huán),按照 先進(jìn)先出原則抽取事件分發(fā)
            while (!eventQueue.isEmpty()) {
            // 從 每次remove(0)可以看出每次都是從隊(duì)列的頭抽取對象
                postSingleEvent(eventQueue.remove(0), postingState);
            }
        } finally {
            postingState.isPosting = false;
            postingState.isMainThread = false;
        }
    }
}

post 里面主要做了以下操作:

  • 從ThreadLocal中獲取PostingState,然后把事件Event添加到隊(duì)列中 postingState.eventQueue
    這里 PostingThreadState 類為:
 /** For ThreadLocal, much faster to set (and get multiple values). */
    final static class PostingThreadState {
        final List<Object> eventQueue = new ArrayList<Object>();
        boolean isPosting;
        boolean isMainThread;
        Subscription subscription;
        Object event;
        boolean canceled;
    }

用來保存一些狀態(tài)

  • 判斷當(dāng)前時(shí)間是否發(fā)送,進(jìn)到 if 中,設(shè)置是否是主線程以及 posting = true,然后循環(huán)調(diào)用隊(duì)列 postingSingleEvent(eventQueue.remove(0), postingState),使用完的事件則被移除出隊(duì)列
  • 最后finally 設(shè)置屬性為false

看下事件處理方法

 private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        //該eventInheritance上面有提到,默認(rèn)為true,即EventBus會考慮事件的繼承樹
        //如果事件繼承自父類,那么父類也會作為事件被發(fā)送
        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);
        }
      // 結(jié)果判斷,如果沒找到訂閱該事件的訂閱者,發(fā)送 NoSubscriberEvent  事件
        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));
            }
        }
    }

Inheritance:遺產(chǎn),繼承

看下調(diào)用的 postingSingleEventForEventType 這個(gè)方法

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
          // 1、根據(jù)事件類型eventType拿到方法集
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                //②保存當(dāng)前狀態(tài)到PostingState
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted = false;
                try {
                    //③開始執(zhí)行
                    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;
    }

調(diào)用postToSubscription來執(zhí)行事件

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

首先獲取threadMode,即訂閱方法運(yùn)行的線程,如果是POSTING,那么直接調(diào)用invokeSubscriber()方法即可,如果是MAIN,則要判斷當(dāng)前線程是否是MAIN線程,如果是也是直接調(diào)用invokeSubscriber()方法,否則會交給mainThreadPoster來處理,其他情況相類似。這里會用到三個(gè)Poster,由于粘性事件也會用到這三個(gè)Poster,因此我把它放到下面來專門講述。而EventBus#invokeSubscriber的實(shí)現(xiàn)也很簡單,主要實(shí)現(xiàn)了利用反射的方式來調(diào)用訂閱方法,這樣就實(shí)現(xiàn)了事件發(fā)送給訂閱者,訂閱者調(diào)用訂閱方法這一過程

invokeSubscriber

void invokeSubscriber(Subscription subscription, Object event) {
    try {
        subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
    } 
    //...
}

整個(gè)流程圖,更加清晰明了


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

相關(guān)閱讀更多精彩內(nèi)容

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