EventBus 原始碼分析(下篇)
上篇ofollow,noindex">EventBus 原始碼分析(上篇) 說到註冊訂閱的前半部分,此篇用來分析傳送事件到接收事件這個過程。
1. 傳送事件
示例:
EventBus.getDefault().post(new RemindBean("2018-02-12","happy"));
post
:
/** Posts the given event to the event bus. */ public void post(Object event) { - 1.獲取當前執行緒的postingThreadState 物件 PostingThreadState postingState = currentPostingThreadState.get(); - 2. 獲取裡面那個事件佇列 List<Object> eventQueue = postingState.eventQueue; - 3. 將事件新增到佇列中去 eventQueue.add(event); - 4. 判斷當前的event 是否在 posting if (!postingState.isPosting) { - 5. 是否是主執行緒 postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper(); postingState.isPosting = true; - 6. 判斷是否取消 if (postingState.canceled) { throw new EventBusException("Internal error. Abort state was not reset"); } try { while (!eventQueue.isEmpty()) {//不為空,進入迴圈 - 7.按照順序,post一個 remove一個 postSingleEvent(eventQueue.remove(0), postingState); } } finally { postingState.isPosting = false; postingState.isMainThread = false; } } }
PostingThreadState
大概看一眼
final static class PostingThreadState { final List<Object> eventQueue = new ArrayList<Object>(); boolean isPosting; boolean isMainThread; Subscription subscription; Object event; boolean canceled; }
再就是postSingleEvent(eventQueue.remove(0), postingState);
方法:
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error { - 1. 獲取event的位元組碼(例如就是:RemindBean.class) Class<?> eventClass = event.getClass(); boolean subscriptionFound = false; if (eventInheritance) {//預設為true - 2. 根據eventClass 的位元組碼查詢 List<Class<?>> eventTypes = lookupAllEventTypes(eventClass); int countTypes = eventTypes.size(); - 3.迴圈遍歷 for (int h = 0; h < countTypes; h++) { Class<?> clazz = eventTypes.get(h); - 4.根據事件,位元組碼查詢訂閱者 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)); } } }
postSingleEventForEventType
:
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) { CopyOnWriteArrayList<Subscription> subscriptions; synchronized (this) { - 1.根據位元組碼取出subscriptions,還記得我們之前在subscribe這個方法的時候, 把subscrber,subscriberMethod 封裝成一個subscription 物件。 subscriptions = subscriptionsByEventType.get(eventClass); } if (subscriptions != null && !subscriptions.isEmpty()) { for (Subscription subscription : subscriptions) { - 2. 取出每一個subscription 物件 postingState.event = event; postingState.subscription = subscription; boolean aborted = false; try { - 3. post到相應的執行緒中回撥 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; }
postToSubscription
: 根據定義的不同執行緒,呼叫相應的方法
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) { switch (subscription.subscriberMethod.threadMode) { case POSTING://一般沒定義的,這個就是post在哪個執行緒,響應就在哪個執行緒執行 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); } }
invokeSubscriber
:
void invokeSubscriber(Subscription subscription, Object event) { try { - 反射拿到位元組碼clazz 反射呼叫方法,就收到訊息了 subscription.subscriberMethod.method.invoke(subscription.subscriber, event); } catch (InvocationTargetException e) { handleSubscriberException(subscription, event, e.getCause()); } catch (IllegalAccessException e) { throw new IllegalStateException("Unexpected exception", e); } }
end.