EventBus 3.x源碼解析

register(注冊)

SubscriberMethod

eventbus注冊的時候回遍歷查詢已經被Subscribe注解的方法(Method)

SubscriberMethod

包含:

  • method:包含了這個方法的全部信息,通過這個屬性,可以反射出該方法,進行調用;
  • threadMode:該方法在什么什么線程下調用;
  • eventType: 事件的類型,會通過該類型自動往該種類型的eventType上追加任務。

1、尋找List<SubscriberMethod>

2、將上面找到的List<SubscriberMethod>依次進行注冊

synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }

這樣,會形成:

subscriptionsByEventType

如上圖的數據結構,這樣就很明確了,一個EventType對應其中所有的對其注冊的Subscription,而Subscription形如:

Subscription

這樣就很清晰了:

Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType這個map中,我們存儲了在何種EventType上面注冊的各種不同注冊者Subscription上面的不同的方法SubscriberMethod

2.1、我們可以想象:
  • subscriptionsByEventType因該是至少使用HashMap作為基本的數據存儲結構的;
  • CopyOnWriteArrayList<Subscription>也需要做判斷重復的工作,因為:不需要放置兩遍同一對象中各種被@Subscribe注解的方法。

所以:
如果你在同一個類中重復調用register方法進行注冊,
譬如:

EventBus.getDefault().register(this);
EventBus.getDefault().register(this);

會拋出異常,這是顯然的。

重復register
2.2、如何進行注冊的

3、發送事件(post)

注意可能會在多線程中進行EventBus的使用,并進行時間的register和post,eventBus有必要進行多線程方面的考慮。

使用ThreadLocal初始化并存儲該線程需要進行發送的事件的容器。

關于ThreadLocal的相關知識,可以參考:http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83]%E8%A7%A3%E5%AF%86ThreadLocal/

/** 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;
}
3.1、發送線程相關狀態的設置
3.2、 postSingleEvent
postSingleEvent(eventQueue.remove(0), postingState);

這段代碼出現一個疑問:postingState中已經持有了eventQueue,為何仍舊需要這樣調用?

3.2.1、eventInheritance

EventBus支持發送的EventClass是否是可以繼承的,應用場景就是:

為了代碼的架構清晰,某些想用的事件不需要傳遞不同的參數,而只需要將各種不同的參數類都繼承于同一個BaseClass或者實現同一個BaseInterface

譬如:小明和小紅是兄妹,兩人在學校里獲得了********同樣的********獎項(這里比喻需要發送相同的事件),現在學校要把獎狀發給小明和小紅,當然,最為直接的就是學校分別把兩張獎狀給小明和小紅,但是,也可以這樣:********學校把獎狀給了小明和小紅的媽媽,由媽媽直接交給兄妹兩人********。這里可以想象到:小明和小紅都“********繼承********”于媽媽。

eventInheritance

這樣,單個事件就開始發送了。

3.3、執行

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 {
     // 在子線程處理需要在UI Thread處理的消息
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case BACKGROUND:
                if (isMainThread) {
                 // 在UI Thread處理需要在子線程處理的消息
                    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);
        }
    }
3.3.1、在子線程處理需要在UI Thread處理的消息

其實就是使用Handler,發送消息到Main Looper中進行輪詢。

mainThreadPoster.enqueue(subscription, event);
其一、PendingPost
PendingPost

這是一個用于構造具體的方法的實體,用于傳遞給Loop是main的Handler進行消息的處理。

值得一提的是:這是一個需要進行反復構造的實體,反復的進行new構造會影響性能,所以構造了一個pendingPostPool進行緩存。這個pool的最大的容量是10000。

synchronized (pendingPostPool) {
            // Don't let the pool grow indefinitely
            if (pendingPostPool.size() < 10000) {
                pendingPostPool.add(pendingPost);
            }
        }
其二、maxMillisInsideHandleMessage

在構造在UI Thread進行發送信息的HandlerPoster的時候,會傳遞一個maxMillisInsideHandleMessage,但是,在想:都是同步方法,計算耗時的意義何在啊?

http://stackoverflow.com/questions/39943133/what-is-maxmillisinsidehandlemessages-meaning-here-could-someone-help-to-answ

3.3.2、在UI Thread處理需要在子線程處理的消息

這種比較容易,使用線程池執行就行了。

eventBus.getExecutorService().execute(this);
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容