EventBus官方介紹爲一個爲Android系統優化的事件訂閱總線,它不只能夠很方便的在同線程中傳遞事件或者對象,還能夠在不一樣線程中實現事件或對象的傳遞,用法比較簡單,能夠很好地完成一些在原生系統中的Intent,Handler等能夠完成的工做,在Android開發過程當中用途及其普遍。固然這裏不介紹它的具體用法,只走源碼,而後本身動手寫一下加深映象。不少人都說用了觀察者設計模式,若是非得要往上靠,只能說不是正常的觀察者。固然咱們也不用太關注,你就認爲它是反射加註解。若是你會 RXjava 也能夠用 RxBus,或者本身用 RxJava 簡單的封裝一下也行。java
我給別人寫的好幾個項目都用了這個開源庫,的確比較方便,能夠減小不少沒必要要的代碼,可是也有某一些問題,就是可讀性並非特別高,跨度有時仍是比較大,固然咱們能夠採用規範來避免掉這些問題。git
分析源碼其實有不少動機,好比:1. 開發中出現了一下問題,報錯或者收不到事件;2. 想了解一下原理,想知道是怎麼個流程;3. 針對性的學習,想吸收裏面的養分,想仔細的學習思想。等等...... 咱們也能從 EventBus 裏面學習到一些有用的知識:github
1. 以前學到的一些設計模式:享元設計模式,單例設計模式,模板設計模式......設計模式
2. 以前學到的一些基礎知識:volatile 關鍵字,線程間的通訊安全,線程池的運用......緩存
3. 反射和註解的一些細節,反射的緩存,方法的修飾符,方法參數的反射......安全
4. 可以參考 EventBus 源碼本身寫一些項目庫,像跨模塊通訊框架,固然大公司像阿里這些都有開源的框架,還用本身寫嗎?其實有時實現方式根本不同,用他們的未必適合本身的運行時架構,其次有時實在是閒着沒事幹。bash
#####1.EventBus.register()markdown
public void register(Object subscriber) { // 首先得到class對象 Class<?> subscriberClass = subscriber.getClass(); // 經過 subscriberMethodFinder 來找到訂閱者訂閱了哪些事件.返回一個 SubscriberMethod 對象的 List, SubscriberMethod // 裏包含了這個方法的 Method 對象,以及未來響應訂閱是在哪一個線程的 ThreadMode ,以及訂閱的事件類型 eventType ,以及訂閱的優 // 先級 priority ,以及是否接收粘性 sticky 事件的 boolean 值,其實就是解析這個類上的全部 Subscriber 註解方法屬性。 List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { // 訂閱 subscribe(subscriber, subscriberMethod); } } } List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) { // 先從緩存裏面讀取,訂閱者的 Class List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass); if (subscriberMethods != null) { return subscriberMethods; } // ignoreGeneratedIndex屬性表示是否忽略註解器生成的MyEventBusIndex。 // ignoreGeneratedIndex的默認值爲false,能夠經過EventBusBuilder來設置它的值 if (ignoreGeneratedIndex) { // 利用反射來獲取訂閱類中全部訂閱方法信息 subscriberMethods = findUsingReflection(subscriberClass); } else { // 從註解器生成的MyEventBusIndex類中得到訂閱類的訂閱方法信息 // 這個這裏不說,能夠去看看以前的編譯時註解 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; } } private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) { FindState findState = prepareFindState(); findState.initForSubscriber(subscriberClass); while (findState.clazz != null) { // 尋找某個類中的全部事件響應方法 findUsingReflectionInSingleClass(findState); findState.moveToSuperclass(); //繼續尋找當前類父類中註冊的事件響應方法 } return getMethodsAndRelease(findState); } 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 循環全部方法 for (Method method : methods) { // 獲取方法訪問修飾符 int modifiers = method.getModifiers(); // 找到全部聲明爲 public 的方法 if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { Class<?>[] parameterTypes = method.getParameterTypes();// 獲取參數的的 Class if (parameterTypes.length == 1) {// 只容許包含一個參數 Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class); if (subscribeAnnotation != null) { // 獲取事件的 Class ,也就是方法參數的 Class Class<?> eventType = parameterTypes[0]; // 檢測添加 if (findState.checkAdd(method, eventType)) { // 獲取 ThreadMode ThreadMode threadMode = subscribeAnnotation.threadMode(); // 往集合裏面添加 SubscriberMethod ,解析方法註解全部的屬性 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"); } } } 複製代碼
先看下 findSubscriberMethods() 這個方法,會經過類對象的 class 去解析這個類中的全部 Subscribe 註解方法的全部屬性值,一個註解方法對應一個 SubscriberMethod 對象,包括 threadMode,priority,sticky,eventType,methodString。該方法執行完畢以後應該是下面這張圖,效果就將就一下吧:架構
// Must be called in synchronized block private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { // 獲取方法參數的 class Class<?> eventType = subscriberMethod.eventType; // 建立一個 Subscription Subscription newSubscription = new Subscription(subscriber, subscriberMethod); // 獲取訂閱了此事件類的全部訂閱者信息列表 CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType); if (subscriptions == null) { // 線程安全的 ArrayList 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(); for (int i = 0; i <= size; i++) { if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) { subscriptions.add(i, newSubscription); break; } } // 經過 subscriber 獲取 List<Class<?>> 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 這個方法,這個相對來講就簡單許多了,把 subscriber , SubscriberMethod 分別存好,到底怎麼存,這個時候看下面這兩個集合:框架
// subscriptionsByEventType 這個集合存放的是?
// key 是 Event 參數的類
// value 存放的是 Subscription 的集合列表
// Subscription 包含兩個屬性,一個是 subscriber 訂閱者(反射執行對象),一個是 SubscriberMethod 註解方法的全部屬性參數值
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
// typesBySubscriber 這個集合存放的是?
// key 是全部的訂閱者
// value 是全部訂閱者裏面方法的參數的 class,eventType
private final Map<Object, List<Class<?>>> typesBySubscriber;
複製代碼
#####2.EventBus.post()
/** Posts the given event to the event bus. */ public void post(Object event) { // currentPostingThreadState 是一個 ThreadLocal, // 他的特色是獲取當前線程一份獨有的變量數據,不受其餘線程影響。 // 這個在 Handler 裏面有過源碼分析 PostingThreadState postingState = currentPostingThreadState.get(); // postingState 就是獲取到的線程獨有的變量數據 List<Object> eventQueue = postingState.eventQueue; // 把 post 的事件添加到事件隊列 eventQueue.add(event); // 若是沒有處在事件發佈狀態,那麼開始發送事件並一直保持發佈狀態 if (!postingState.isPosting) { // 是不是主線程 postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper(); // isPosting = true postingState.isPosting = true; if (postingState.canceled) { throw new EventBusException("Internal error. Abort state was not reset"); } try { while (!eventQueue.isEmpty()) { postSingleEvent(eventQueue.remove(0), postingState); } } finally { postingState.isPosting = false; postingState.isMainThread = false; } } } 複製代碼
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error { // 獲得事件的Class 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); // 依次向 eventClass 的父類或接口的訂閱方法發送事件 // 只要有一個事件發送成功,返回 true ,那麼 subscriptionFound 就爲 true subscriptionFound |= postSingleEventForEventType(event, postingState, clazz); } } else { // 發送事件 subscriptionFound = postSingleEventForEventType(event, postingState, eventClass); } // 若是沒有訂閱者 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)); } } } private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) { CopyOnWriteArrayList<Subscription> subscriptions; synchronized (this) { // 獲得Subscription 列表 subscriptions = subscriptionsByEventType.get(eventClass); } if (subscriptions != null && !subscriptions.isEmpty()) { // 遍歷 subscriptions 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; } 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); } } 複製代碼
到這裏咱們基本就把核心的內容解析完了,重點就是去遍歷 typesBySubscriber 找出知足需求的而後反射執行對應的方法,至於在哪裏執行這個就須要判斷 threadMode。
#####3.EventBus.unregister()
/** 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 { Log.w(TAG, "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) { // 獲取事件類的全部訂閱信息列表,將訂閱信息從訂閱信息集合中移除,同時將訂閱信息中的active屬性置爲FALSE 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) { // 將訂閱信息激活狀態置爲FALSE subscription.active = false; // 將訂閱信息從集合中移除 subscriptions.remove(i); i--; size--; } } } } 複製代碼
全部分享大綱:Android進階之旅 - 系統架構篇
視頻講解地址:http://pan.baidu.com/s/1sl6wvBf