The EventBus Register () logic is analyzed, and the post() logic is continued.

/** Posts the given event to the event bus. */ public void post(Object event) { //currentPostingThreadState Is a ThreadLocal type PostingThreadState postingState = currentPostingThreadState. The get (); List<Object> eventQueue = postingState.eventQueue; eventQueue.add(event); // Determine whether an event is being sent to prevent the event from being called 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 {// loop the event while (! eventQueue.isEmpty()) { postSingleEvent(eventQueue.remove(0), postingState); } } finally { postingState.isPosting = false; postingState.isMainThread = false; Final static class PostingThreadState {final List<Object> eventQueue = new ArrayList<Object>(); // Message queue Boolean isPosting; // Whether Boolean isMainThread is being sent; // Whether the thread is in the main thread Object event; // Send the event Boolean canceled; }Copy the code

The POST () method first builds a PostingThreadState, puts the event into the eventQueue, and then sends the event through a while loop.

Private void postSingleEvent(Object Event, PostingThreadState postingState) throws Error {// Obtain the event Class<? > eventClass = event.getClass(); boolean subscriptionFound = false; If (eventInheritance) {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); } 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)); }}}Copy the code

After entering the postSingleEventForEventType () method.

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<? > eventClass) { CopyOnWriteArrayList<Subscription> subscriptions; Synchronized (this) {/ / by class, the class for subscription subscriptions = subscriptionsByEventType. The relationship between the get (eventClass); } if (subscriptions ! = null && ! subscriptions.isEmpty()) { for (Subscription subscription : subscriptions) { postingState.event = event; postingState.subscription = subscription; boolean aborted = false; Try {/ / sending, processing events 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; }Copy the code

This method obtains all the corresponding subscriptions through event and sends each subscription.

// Note the four ways in which ThreadMode is initialized. // Subscribe from @subscribe. Private void postToSubscription(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); }}Copy the code

Wake up the subscriber for processing

// By reflection, Void invokeSubscriber to wake up subscribers to handle events Object event) { try { subscription.subscriberMethod.method.invoke(subscription.subscriber, event); } catch (InvocationTargetException e) { handleSubscriberException(subscription, event, e.getCause()); } catch (IllegalAccessException e) { throw new IllegalStateException("Unexpected exception", e); }}Copy the code

MainThreadPoster inherits from HandlerPoster and is a handler

final class HandlerPoster extends Handler { private final PendingPostQueue queue; private final int maxMillisInsideHandleMessage; Private final EventBus EventBus; private boolean handlerActive; HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) { super(looper); this.eventBus = eventBus; this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage; queue = new PendingPostQueue(); } void enqueue(Subscription subscription, Object event) { PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event); Synchronized (this) {queue. Enqueue (pendingPost); if (! handlerActive) { handlerActive = true; if (! sendMessage(obtainMessage())) { throw new EventBusException("Could not send handler message"); } } } } @Override public void handleMessage(Message msg) { boolean rescheduled = false; try { long started = SystemClock.uptimeMillis(); PendingPost = queue.poll(); PendingPost = queue. Poll (); if (pendingPost == null) { synchronized (this) { // Check again, this time in synchronized pendingPost = queue.poll(); if (pendingPost == null) { handlerActive = false; return; }}} / / by reflection to awaken the subscriber handle events eventBus. InvokeSubscriber (pendingPost); long timeInMethod = SystemClock.uptimeMillis() - started; if (timeInMethod >= maxMillisInsideHandleMessage) { if (! sendMessage(obtainMessage())) { throw new EventBusException("Could not send handler message"); } rescheduled = true; return; } } } finally { handlerActive = rescheduled; }}}Copy the code

InvokeSubscriber calls inovkeSubScriber() of eventBus.

void invokeSubscriber(PendingPost pendingPost) { Object event = pendingPost.event; Subscription subscription = pendingPost.subscription; . / / recycling pendingPost pendingPost releasePendingPost (pendingPost); if (subscription.active) { invokeSubscriber(subscription, event); } } void invokeSubscriber(Subscription subscription, Object event) { try { subscription.subscriberMethod.method.invoke(subscription.subscriber, event); } catch (InvocationTargetException e) { handleSubscriberException(subscription, event, e.getCause()); } catch (IllegalAccessException e) { throw new IllegalStateException("Unexpected exception", e); }}Copy the code

backgroundPoster

/** * Posts events in background. * * @author Markus */ final class BackgroundPoster implements Runnable { private final  PendingPostQueue queue; private final EventBus eventBus; private volatile boolean executorRunning; BackgroundPoster(EventBus eventBus) { this.eventBus = eventBus; queue = new PendingPostQueue(); } public void enqueue(Subscription subscription, Object event) { PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event); synchronized (this) { queue.enqueue(pendingPost); if (! executorRunning) { executorRunning = true; / / execute the background thread eventBus. GetExecutorService (). The execute (this); } } } @Override public void run() { try { try { while (true) { PendingPost pendingPost = queue.poll(1000); if (pendingPost == null) { synchronized (this) { // Check again, this time in synchronized pendingPost = queue.poll(); if (pendingPost == null) { executorRunning = false; return; } } } eventBus.invokeSubscriber(pendingPost); } } catch (InterruptedException e) { Log.w("Event", Thread.currentThread().getName() + " was interruppted", e); } } finally { executorRunning = false; }}}Copy the code

asyncPoster

/** * Posts events in background. * * @author Markus */ class AsyncPoster implements Runnable { private final PendingPostQueue queue; private final EventBus eventBus; AsyncPoster(EventBus eventBus) { this.eventBus = eventBus; queue = new PendingPostQueue(); } public void enqueue(Subscription subscription, Object event) { PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event); queue.enqueue(pendingPost); / / execute the background thread eventBus. GetExecutorService (). The execute (this); } @Override public void run() { PendingPost pendingPost = queue.poll(); if(pendingPost == null) { throw new IllegalStateException("No pending post available"); } eventBus.invokeSubscriber(pendingPost); }}Copy the code

Compared with the other two posters, asyncPoster is executed directly without judgment, which is related to its corresponding THreadMode. No matter what thread the sender is in, a background thread is started to process it. After looking at the post() method, move on to the postSticky() method

/** * Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky * event of an event's type is kept in memory for future access by subscribers using {@link Subscribe#sticky()}. */ public Void postSticky(Object event) {// Add synchronization lock, Call post() method synchronized (stickyEvents) {stickyEvents. Put (event.getClass(), event); } // Should be posted after it is putted, in case the subscriber wants to remove immediately post(event); }Copy the code

The event is added to the stickyEvent queue, and the POST () method is called to send the event.

At this point, the process of sending is analyzed, but not yet. There is also the unRegister() method. Keep looking.

/** Unregisters the given subscriber from all event classes. */ public synchronized void unregister(Object subscriber) { // Get all of the subscriber's data types by subscriber, iterate through each type, unbind List<Class<? >> subscribedTypes = typesBySubscriber.get(subscriber); if (subscribedTypes ! = null) { for (Class<? > eventType : subscribedTypes) { unsubscribeByEventType(subscriber, eventType); } // Remove typesbysubscriber.remove (subscriber) from the data set; } else { Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass()); } } /** Unregisters the given subscriber from all event classes. */ public synchronized void unregister(Object Subscriber) {// According to the subscriber, get all the data types of the subscriber, traverse each type, unbind List<Class<? >> subscribedTypes = typesBySubscriber.get(subscriber); if (subscribedTypes ! = null) { for (Class<? > eventType : subscribedTypes) { unsubscribeByEventType(subscriber, eventType); } // Remove typesbysubscriber.remove (subscriber) from the data set; } else { Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass()); }}Copy the code

The unbinding operation is very simple. The two data sets used are the collections updated when register.

The general process has been analyzed, but there are still some small points that I haven’t figured out. In the next few days, I will continue to clarify a few points and update the article. If there are mistakes, don’t hesitate to advise.