天天看點

EventBus3.0源碼淺析與了解

1.簡介

EventBus 是一個 Android 事件釋出/訂閱架構。

傳統的事件傳遞方式包括:Handler(消息處理機制,一般用于更新UI)、BroadCastReceiver(廣播接收者)、Interface 回調。

EventBus優點:

  • Activity、Fragment、Service與線程之間的通訊是很常見的,EventBus正好可以屏蔽一些線程切換問題,簡單地實作釋出訂閱功能。
  • 代碼簡潔,使用簡單,并将事件釋出和訂閱充分解耦。

EventBus缺點:

  • 他的代碼邏輯不是很清楚,在 Subscriber 注冊的時候,Subscriber 中的方法會被周遊查找以 onEvent 開頭的 public 方法,而Interface 回調則是查找實作者。
  • 而且若是EventBus傳遞較多類型的消息,那麼消息類的數量必然是會爆炸性增長。
  • 調試的時候必須熟悉代碼,不然不斷點你是沒辦法找到Subscribe的方法的資料來源。

使用方法

注冊訂閱者

@Override
  public void onCreate() {
    //3.0版本的注冊,2.x不再介紹
    EventBus.getDefault().register(this);
}
           

編寫響應事件訂閱方法

我們可以自定義自己的事件類,例如:

public class CreateFolderEvent {
  //一個建立檔案夾的事件
    public File folder;
    public String parentPath;

    public CreateFolderEvent(File folder, String parentPath) {
        this.folder = folder;
        this.parentPath = parentPath;
    }
}
           

注冊之後,我們接着編寫響應事件的方法,如下:

//threadMode和sticky使用下文會講
    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onReceiveCreateFolderEvent(CreateFolderEvent event) {

      Log.e("Subscribe",event.parentPath);
    }
           

發送自定義事件(自定義的 EventType)

通過EventBus的post()方法來發送事件,對應的接收方就會收到資訊并通過Event來擷取傳遞的對象.EventBus或者通過postSticky()來發送一個粘性事件.

粘性事件:何為黏性事件呢?簡單講,就是在發送事件之後再訂閱該事件也能收到該事件,跟黏性廣播類似。

舉例場景:如我想發送一個事件給一個Activity,但是那個activity還沒有建立。又想讓activity建立時收到,可以用postSticky()。

示例如下:

private void updateCreateFolderUI(String message) {
        File item = new File();
        mCurrentPath="/Sdcard/";
       EventBus().getDefault().post(new CreateFolderEvent(item, mCurrentPath));
       //或者是
       EventBus().getDefault().postSticky(new CreateFolderEvent(item, mCurrentPath));
    }
           

解除EventBus注冊

一般在onDestory()方法中取消訂閱:防止記憶體溢出。

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

EventBus 主要類的關系圖.

從中我們也可以看出大部分類都與 EventBus 直接關聯。上部分主要是訂閱者相關資訊,中間是 EventBus 類,下面是釋出者釋出事件後的調用。

EventBus3.0源碼淺析與了解

使用方法介紹完了,下面讓我們來對EventBus進行簡單的源碼分析

EventBus 源碼解析

EventBus的訂閱者、釋出者、EventBus 關系圖與事件響應流程流程,通過我們熟悉的使用方法來深入到EventBus的實作内部并了解其實作原理.

EventBus3.0源碼淺析與了解
EventBus3.0源碼淺析與了解

建立EventBus

EventBus 類負責所有對外暴露的 API,其中的 register()、post()、unregister() 函數配合上自定義的 EventType 及事件響應函數即可完成核心功能

EventBus3.0源碼淺析與了解

一般情況下我們都是通過EventBus.getDefault()擷取到EventBus對象,進入源碼檢視其實作:

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

        return defaultInstance;
    }
           

這裡獲得對象的模式是常用的單例模式了,目的是為了保證getDefault()得到的都是同一個執行個體。如果不存在執行個體,則會調用EventBus的構造方法:

private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();

  public static EventBusBuilder builder() {
        return new EventBusBuilder();
    }



   EventBus(EventBusBuilder builder) {
        this.currentPostingThreadState = new ThreadLocal() {
            protected EventBus.PostingThreadState initialValue() {
                return new EventBus.PostingThreadState();
            }
        };
            //key:訂閱的事件,value:訂閱這個事件的所有訂閱者集合
            //private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
            subscriptionsByEventType = new HashMap<>();
            //key:訂閱者對象,value:這個訂閱者訂閱的事件集合
            //private final Map<Object, List<Class<?>>> typesBySubscriber;
            typesBySubscriber = new HashMap<>();
            //粘性事件 key:粘性事件的class對象, value:事件對象
            //private final Map<Class<?>, Object> stickyEvents;
            stickyEvents = new ConcurrentHashMap<>();
            //事件主線程處理
            mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), );
            //事件 Background 處理
            backgroundPoster = new BackgroundPoster(this);
            //事件異步線程處理
            asyncPoster = new AsyncPoster(this);
            indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : ;
            //訂閱者響應函數資訊存儲和查找類
            subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
            builder.strictMethodVerification, builder.ignoreGeneratedIndex);
            logSubscriberExceptions = builder.logSubscriberExceptions;
            logNoSubscriberMessages = builder.logNoSubscriberMessages;
            sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
            sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
            throwSubscriberException = builder.throwSubscriberException;
            //是否支援事件繼承
            eventInheritance = builder.eventInheritance;
            executorService = builder.executorService;
            //此處參考http://www.jianshu.com/p/f057c460c77e
  }
           

從上面代碼可以看出EventBus通過初始化一個EventBusBuilder()對象來初始化EventBus的一些配置。

訂閱者的注冊

 在擷取到EventBus對象以後,我們就可以将訂閱者注冊到EventBus中。

register()方法的實作

public void register(Object subscriber) {
        //首先獲得訂閱者的class對象
        Class subscriberClass = subscriber.getClass();
        /通過subscriberMethodFinder來找到訂閱者訂閱了哪些事件.傳回一個SubscriberMethod對象的List,SubscriberMethod
        //裡包含了這個方法的Method對象,以及将來響應訂閱是在哪個線程的ThreadMode
        //以及訂閱的事件類型eventType,以及訂閱的優
        //先級priority,以及是否接收粘性sticky事件的boolean值.
        List subscriberMethods = this.subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized(this) {
            Iterator var5 = subscriberMethods.iterator();

            while(var5.hasNext()) {
                SubscriberMethod subscriberMethod = (SubscriberMethod)var5.next();
                //訂閱
                this.subscribe(subscriber, subscriberMethod);
            }

        }
    }
           

SubscriberMethodFinder類就是用來查找和緩存訂閱者響應函數的資訊的類。

3.0版本中,EventBus提供了一個EventBusAnnotationProcessor注解處理器來在編譯期通過讀取@Subscribe()注解并解析,處理其中所包含的資訊,然後生成java類來儲存所有訂閱者關于訂閱的資訊,這樣就比在運作時使用反射來獲得這些訂閱者的資訊速度要快.

SubscriberMethod裡包含了需要執行subscribe()的資訊,下面進入findSubscriberMethods()方法源碼中檢視:

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    //先從METHOD_CACHE取看是否有緩存,key:儲存訂閱類的類名,value:儲存類中訂閱的方法資料,
    List subscriberMethods = (List)METHOD_CACHE.get(subscriberClass);
    if(subscriberMethods != null) {
        return subscriberMethods;
    } else {
        //是否忽略注解器生成的MyEventBusIndex類
        if(this.ignoreGeneratedIndex) {
            //利用反射來讀取訂閱類中的訂閱方法資訊
            subscriberMethods = this.findUsingReflection(subscriberClass);
        } else {
            subscriberMethods = this.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緩存
            METHOD_CACHE.put(subscriberClass, subscriberMethods);
            return subscriberMethods;
        }
    }
}

           

下面我們來看findUsingInfo()方法的源碼實作:

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        SubscriberMethodFinder.FindState findState = this.prepareFindState();
        //FindState 用來做訂閱方法的校驗和儲存
        findState.initForSubscriber(subscriberClass);

        for(; findState.clazz != null; findState.moveToSuperclass()) {
            findState.subscriberInfo = this.getSubscriberInfo(findState);
            if(findState.subscriberInfo != null) {
                SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
                SubscriberMethod[] var4 = array;
                int var5 = array.length;

                for(int var6 = ; var6 < var5; ++var6) {
                    SubscriberMethod subscriberMethod = var4[var6];
                    if(findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                        findState.subscriberMethods.add(subscriberMethod);
                    }
                }
            } else {
                this.findUsingReflectionInSingleClass(findState);
            }
        }

        return this.getMethodsAndRelease(findState);
    }
           

findUsingInfo是通過查找我們上面所說的EventBusIndex類中的資訊,來轉換成List進而獲得訂閱類的相關訂閱函數的各種資訊.

接着讓我們進入findUsingReflection()方法:

private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        SubscriberMethodFinder.FindState findState = this.prepareFindState();
        findState.initForSubscriber(subscriberClass);

        while(findState.clazz != null) {
            //通過反射來獲得訂閱方法資訊
            this.findUsingReflectionInSingleClass(findState);
             //查找父類的訂閱方法
            findState.moveToSuperclass();
        }
        //擷取findState中的SubscriberMethod(訂閱方法List)并傳回
        return this.getMethodsAndRelease(findState);
    }
           

FindState類做訂閱方法的校驗和儲存,FIND_STATE_POOL靜态數組來儲存FindState對象,FindState複用,避免重複建立過多的對象.最終通過findUsingReflectionInSingleClass()來具體獲得相關訂閱方法的資訊:

private void findUsingReflectionInSingleClass(SubscriberMethodFinder.FindState findState) {
        Method[] methods;
        try {
            //獲得聲明的所有方法
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable var12) {
            //異常則擷取公開方法
            methods = findState.clazz.getMethods();
            findState.skipSuperClasses = true;
        }

        Method[] th = methods;
        int var4 = methods.length;

        for(int var5 = ; var5 < var4; ++var5) {
            Method method = th[var5];
            //傳回int類型值表示該字段的修飾符
            int modifiers = method.getModifiers();
            if((modifiers & ) !=  && (modifiers & ) == ) {
                Class[] var13 = method.getParameterTypes();
                if(var13.length == ) {
                    Subscribe methodName1 = (Subscribe)method.getAnnotation(Subscribe.class);
                    if(methodName1 != null) {
                        Class eventType = var13[];
                        if(findState.checkAdd(method, eventType)) {
                            ThreadMode threadMode = methodName1.threadMode();
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode, methodName1.priority(), methodName1.sticky()));
                        }
                    }
                } else if(this.strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                    String var14 = method.getDeclaringClass().getName() + "." + method.getName();
                    throw new EventBusException("@Subscribe method " + var14 + "must have exactly 1 parameter but has " + var13.length);
                }
            } else if(this.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");
            }
        }

    }
           

至此,在register()方法中,訂閱類的所有SubscriberMethod都已經被儲存了,最後再通過getMethodsAndRelease()傳回List。

接着,我們檢視register()方法中的訂閱事件

synchronized(this) {
            //擷取到所有的訂閱方法,一一訂閱
           Iterator var5 = subscriberMethods.iterator();
            while(var5.hasNext()) {
               SubscriberMethod subscriberMethod = (SubscriberMethod)var5.next();
               this.subscribe(subscriber, subscriberMethod);
           }

       }
           

進入subscribe(subscriber, subscriberMethod);源碼檢視下。

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        ////擷取訂閱的事件類型 普通事件和粘性事件
        Class eventType = subscriberMethod.eventType;
        ////建立Subscription對象
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        //從subscriptionsByEventType裡檢查是否已經添加過該Subscription
        CopyOnWriteArrayList subscriptions = (CopyOnWriteArrayList)this.subscriptionsByEventType.get(eventType);
        if(subscriptions == null) {
            //未添加則建立
            subscriptions = new CopyOnWriteArrayList();
            this.subscriptionsByEventType.put(eventType, subscriptions);
        } else if(subscriptions.contains(newSubscription)) {
            //如果添加過就抛出異常
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);
        }
        //根據優先級priority來添加Subscription對象
        int size = subscriptions.size();

        for(int subscribedEvents = ; subscribedEvents <= size; ++subscribedEvents) {
            if(subscribedEvents == size || subscriberMethod.priority > ((Subscription)subscriptions.get(subscribedEvents)).subscriberMethod.priority) {
                subscriptions.add(subscribedEvents, newSubscription);
                break;
            }
        }
        //将訂閱者對象以及訂閱的事件儲存到typesBySubscriber裡.
        //  private final Map<Object, List<Class<?>>> typesBySubscriber
        Object var13 = (List)this.typesBySubscriber.get(subscriber);
        if(var13 == null) {
            var13 = new ArrayList();
            this.typesBySubscriber.put(subscriber, var13);
        }

        ((List)var13).add(eventType);
        //如果事件的類型是sticky,則立即分發sticky事件
        if(subscriberMethod.sticky) {
            if(this.eventInheritance) {
                //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 stickyEvent = this.stickyEvents.entrySet();
                Iterator var9 = stickyEvent.iterator();

                while(var9.hasNext()) {
                    Entry entry = (Entry)var9.next();
                    Class candidateEventType = (Class)entry.getKey();
                    if(eventType.isAssignableFrom(candidateEventType)) {
                        Object stickyEvent1 = entry.getValue();
                        //分發sticky事件給訂閱者
                        this.checkPostStickyEventToSubscription(newSubscription, stickyEvent1);
                    }
                }
            } else {
                Object var14 = this.stickyEvents.get(eventType);
                //分發sticky事件給訂閱者
                this.checkPostStickyEventToSubscription(newSubscription, var14);
            }
        }

    }
           

下面抄圖展示register() 函數流程:

EventBus3.0源碼淺析與了解

事件分發過程源碼分析(post與postSticky)

public void postSticky(Object event) {
          //最終會調用post(Object event)
          Map var2 = this.stickyEvents;
          synchronized(this.stickyEvents) {
              //将event放入 private final Map<Class<?>, Object> stickyEvents的map中
              this.stickyEvents.put(event.getClass(), event);
          }

          this.post(event);
      }

    public void post(Object event) {
         //得到目前線程的postingState狀态
        EventBus.PostingThreadState postingState = (EventBus.PostingThreadState)this.currentPostingThreadState.get();
        //擷取目前線程的事件隊列
        List eventQueue = postingState.eventQueue;
        eventQueue.add(event);
        if(!postingState.isPosting) {
            //判斷是否是主線程
            postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
            postingState.isPosting = true;
            if(postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }

            try {
                while(!eventQueue.isEmpty()) {
                    //若果不是空,則分發事件
                    this.postSingleEvent(eventQueue.remove(), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }

    }
           

currentPostingThreadState的實作是一個包含了PostingThreadState的ThreadLocal對象

private final ThreadLocal<EventBus.PostingThreadState> currentPostingThreadState;

 EventBus(EventBusBuilder builder) {
        this.currentPostingThreadState = new ThreadLocal() {
            protected EventBus.PostingThreadState initialValue() {
                return new EventBus.PostingThreadState();
            }
        };
   }
           

PostingThreadState類如下:

static final class PostingThreadState {
        final List<Object> eventQueue = new ArrayList();
        boolean isPosting;
        boolean isMainThread;
        Subscription subscription;
        Object event;
        boolean canceled;

        PostingThreadState() {
        }
    }
           

ThreadLocal用于實作在不同的線程中存儲線程私有資料的類。在多線程的環境中,當多個線程需要對某個變量進行頻繁操作,同時各個線程間不需要同步,此時,各個子線程隻需要對存儲在目前線程中的變量的拷貝進行操作即可,程式的運作效率會很高,即所謂的空間換時間。

Android版的ThreadLocal和java原生的ThreadLocal有一定的差别,android版的進行了一些優化設計,通過内部類Values中的Object數組來存儲ThreadLocal的弱引用和線程的局部資料對象;而java版的是以MAP的方式來存儲。

具體請檢視Android開發之ThreadLocal原理深入了解

接下來我們進入postSingleEvent(eventQueue.remove(0), postingState)去檢視:

try {
                while(!eventQueue.isEmpty()) {
                    this.postSingleEvent(eventQueue.remove(), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
           

postSingleEvent(eventQueue.remove(0), postingState)包含的幾個主要方法一并列出:

private void postSingleEvent(Object event, EventBus.PostingThreadState postingState) throws Error {
        Class eventClass = event.getClass();
        boolean subscriptionFound = false;
        //是否觸發訂閱了該事件(eventClass)的父類,以及接口的類的響應方法.
        if(this.eventInheritance) {
            //查找eventClass類所有的父類以及接口
            List eventTypes = lookupAllEventTypes(eventClass);
            int countTypes = eventTypes.size();

            for(int h = ; h < countTypes; ++h) {
                Class clazz = (Class)eventTypes.get(h);
                //右邊有一個為true,subscriptionFound屬性為true
                subscriptionFound |= this.postSingleEventForEventType(event, postingState, clazz);
            }
        } else {
            //post單個事件
            subscriptionFound = this.postSingleEventForEventType(event, postingState, eventClass);
        }

        if(!subscriptionFound) {
            //如果未發現
            if(this.logNoSubscriberMessages) {
                Log.d(TAG, "No subscribers registered for event " + eventClass);
            }

            if(this.sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) {
              //滿足上述條件則發送空事件
                this.post(new NoSubscriberEvent(this, event));
            }
        }

    }

    private boolean postSingleEventForEventType(Object event, EventBus.PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList subscriptions;
        synchronized(this) {
          //擷取訂閱了這個事件的Subscription清單.
            subscriptions = (CopyOnWriteArrayList)this.subscriptionsByEventType.get(eventClass);
        }

        if(subscriptions != null && !subscriptions.isEmpty()) {
            Iterator var5 = subscriptions.iterator();

            while(var5.hasNext()) {
                Subscription subscription = (Subscription)var5.next();
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted = false;

                try {
                    //一個個将事件分發給訂閱者
                    this.postToSubscription(subscription, event, postingState.isMainThread);
                    aborted = postingState.canceled;
                } finally {
                    //将postingState置為初始狀态
                    postingState.event = null;
                    postingState.subscription = null;
                    postingState.canceled = false;
                }

                if(aborted) {
                  //如果被中斷,結束整個循環體
                    break;
                }
            }

            return true;
        } else {
            return false;
        }
    }


  //postToSubscription()通過不同的threadMode在不同的線程裡invoke()訂閱者的方法
    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch(null.$SwitchMap$com$inno$eventbus$ThreadMode[subscription.subscriberMethod.threadMode.ordinal()]) {
        case :
            this.invokeSubscriber(subscription, event);
            break;
        case :
            if(isMainThread) {
                this.invokeSubscriber(subscription, event);
            } else {
                this.mainThreadPoster.enqueue(subscription, event);
            }
            break;
        case :
            if(isMainThread) {
                this.backgroundPoster.enqueue(subscription, event);
            } else {
                this.invokeSubscriber(subscription, event);
            }
            break;
        case :
            this.asyncPoster.enqueue(subscription, event);
            break;
        default:
            throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }

    }

    //通過反射調用了訂閱者的訂閱函數并把event對象作為參數傳入
    void invokeSubscriber(Subscription subscription, Object event) {
            try {
                subscription.subscriberMethod.method.invoke(subscription.subscriber, new Object[]{event});
            } catch (InvocationTargetException var4) {
                this.handleSubscriberException(subscription, event, var4.getCause());
            } catch (IllegalAccessException var5) {
                throw new IllegalStateException("Unexpected exception", var5);
            }
  }

           

ThreadMode共有四類:

  • PostThread:預設的 ThreadMode,表示在執行 Post 操作的線程直接調用訂閱者的事件響應方法,不論該線程是否為主線程(UI 線程)。當該線程為主線程時,響應方法中不能有耗時操作,否則有卡主線程的風險。适用場景:對于是否在主線程執行無要求,但若 Post 線程為主線程,不能耗時的操作;
  • MainThread:在主線程中執行響應方法。如果釋出線程就是主線程,則直接調用訂閱者的事件響應方法,否則通過主線程的 Handler 發送消息在主線程中處理——調用訂閱者的事件響應函數。顯然,MainThread類的方法也不能有耗時操作,以避免卡主線程。适用場景:必須在主線程執行的操作;
  • BackgroundThread:在背景線程中執行響應方法。如果釋出線程不是主線程,則直接調用訂閱者的事件響應函數,否則啟動唯一的背景線程去處理。由于背景線程是唯一的,當事件超過一個的時候,它們會被放在隊列中依次執行,是以該類響應方法雖然沒有PostThread類和MainThread類方法對性能敏感,但最好不要有重度耗時的操作或太頻繁的輕度耗時操作,以造成其他操作等待。适用場景:操作輕微耗時且不會過于頻繁,即一般的耗時操作都可以放在這裡;
  • Async:不論釋出線程是否為主線程,都使用一個空閑線程來處理。和BackgroundThread不同的是,Async類的所有線程是互相獨立的,是以不會出現卡線程的問題。适用場景:長耗時操作,例如網絡通路。

    引用位址

post()整體流程圖如下

EventBus3.0源碼淺析與了解

EventBus解除注冊源碼分析

解除注冊隻要調用unregister()方法即可實作

public synchronized void unregister(Object subscriber) {
     //通過typesBySubscriber來取出這個subscriber訂閱者訂閱的事件類型,
        List subscribedTypes = (List)this.typesBySubscriber.get(subscriber);
        if(subscribedTypes != null) {
          //如果不是null
            Iterator var3 = subscribedTypes.iterator();

            while(var3.hasNext()) {
                Class eventType = (Class)var3.next();
                //分别解除每個訂閱了的事件類型
                this.unsubscribeByEventType(subscriber, eventType);
            }

            this.typesBySubscriber.remove(subscriber);
        } else {
            Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }

    }

    private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
          List subscriptions = (List)this.subscriptionsByEventType.get(eventType);
          //subscriptionsByEventType裡拿出這個事件類型的訂閱者清單.
          if(subscriptions != null) {
              int size = subscriptions.size();

              for(int i = ; i < size; ++i) {
                //分别取消訂閱
                  Subscription subscription = (Subscription)subscriptions.get(i);
                  if(subscription.subscriber == subscriber) {
                      subscription.active = false;
                      subscriptions.remove(i);
                      --i;
                      --size;
                  }
              }
          }

      }

           

從上面代碼可以看出最終從typesBySubscriber和subscriptions裡分别移除訂閱者以及相關資訊,完成反注冊.

源碼已經進行了簡單的分析,而且EventBus的總體積大小是52K,總體來看EventBus還是很值得我們在項目中使用的。盡快使用它吧!

EventBus3.0jar包下載下傳位址