EventBus source code analysis 2

Analysis of EventBus.getDefault().post() method

public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState. eventQueue ;
eventQueue.add(event) ;

if (!postingState.isPosting) {
postingState. isMainThread = isMainThread() ;
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;
}
}
}
  

As you can see, after adding the event object to the eventQueue, then execute postSingleEvnet()

click in

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        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) {
                logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }

It is known from debug that the enventInheritance is true here, then the statement below if (evnetInheritance) will be executed,
lookupEventTypes is to get all eventTypes from the cache, which will be analyzed below
After getting all evnetTypes, execute postSingleEventForType() in a loop

Look at postSingleEventForType below

  private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            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;
    }


可以看到这里用了CopyOnWriteArrayList<Subscription> ,可以理解为是一个线程安全的ArrayList
然后还有一个重要的类Subscription,

点进去看
final class Subscription {
    final Object subscriber;
    final SubscriberMethod subscriberMethod;
    /**
     * Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery
     * {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
     */
    volatile boolean active;
    Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
        this.subscriber = subscriber;
        this.subscriberMethod = subscriberMethod;
        active = true;
    }
    @Override
    public boolean equals(Object other) {
        if (other instanceof Subscription) {
            Subscription otherSubscription = (Subscription) other;
            return subscriber == otherSubscription.subscriber
                    && subscriberMethod.equals(otherSubscription.subscriberMethod);
        } else {
            return false;
        }
    }
    @Override
    public int hashCode() {
        return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
    }
}

Subscription就只是把一个subsciber和 subscriberMehtod 另外加一个boolean变量active放在了一个对象中
这样有什么用呢?我的理解是,一个subscription代表一个订阅事件,因为一个event post出去,可能有多个
subscriber接收到,那么一个subscriber和一个event绑定就是一个订阅事件,多个subscriber和同一个event,
就是多个订阅事件

继续看 postSingleEventForEventType

subscriptions = subscriptionsByEventType .get(eventClass) ;

看这句,从subscriptionByEventType中获取subscriptons
这个subscriptionsByEventType是什么,它是一个Map,它里面的value是在EventBus.getDefault().register(this)
建立订阅时put进去的,请参考EventBus源码分析1

拿到subscriptions后,就开始循环执行  postToSubscription

点进去

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 MAIN_ORDERED:
                if (mainThreadPoster != null) {
                    mainThreadPoster.enqueue(subscription, event);
                } else {
                    // temporary: technically not correct as poster not decoupled from subscriber
                    invokeSubscriber(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);
        }
    }


可以看,这里是根据threadMode区分执行
我们在MainActivity中的,threadMode是MAIN
那么这里就执行
  if (isMainThread) {
             invokeSubscriber(subscription, event);
     } else {
             mainThreadPoster.enqueue(subscription, event);
  }

由Debug得知,isMainThread是true
那么就执行invokeSubscriber(),点进去

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);
}
}

可以看到,这里在用反射的方式,用Method.invoke的方式调用方法
实际就是在调用@Subscribe(threadMode = MAIN)下面的方法

综上分析,就是实现了post一个Event对象后,调用关联的方法的过程

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324373800&siteId=291194637