- methodName);
}
}
}
clazz = clazz.getSuperclass();
}
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass + " has no public methods called "
- ON_EVENT_METHOD_NAME);
} else {
synchronized (methodCache) {
methodCache.put(key, subscriberMethods);
}
return subscriberMethods;
}
}
上面就是获取传入对象class的方法的方法。其中前半部分是先去缓存查找是否有这个类的记录,如果有直接返回,没有继续执行。当没有时继续走到Method[] methods = clazz.getDeclaredMethods();
语句得到该类的所有方法;接着那个大for循环就是遍历这个类匹配符合封装要求的method;其中,if (methodName.startsWith(ON_EVENT_METHOD_NAME))
用来判断方法名是不是以“onEvent”开头;接着if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0)
用于继续判断是否是public且非static和abstract方法;if (parameterTypes.length == 1)
用于继续判断是否是一个参数。如果都复合,才进入封装的部分;接着也比较简单,根据方法的后缀,来确定threadMode,threadMode是个四种情况的枚举类型(前面基础使用一篇解释过四种类型);接着通过subscriberMethods.add(new SubscriberMethod(method, threadMode, eventType));
把method添加到subscriberMethods列表;接着通过clazz = clazz.getSuperclass();
扫描父类的方法;接着while结束,扫描完后通过methodCache.put(key, subscriberMethods);
将方法放入缓存,然后返回List<SubscriberMethod>
的方法列表(订阅者方法至此查找完成)。
接着继续回到上一级方法:
private synchronized void register(Object subscriber, boolean sticky, int priority) {
List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod, sticky, priority);
}
}
通过for循环遍历List<SubscriberMethod>
里的方法,同时传入suscribe方法。具体如下:
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
//从订阅方法中拿到订阅事件的类型
Class<?> eventType = subscriberMethod.eventType;
通过订阅事件类型,找到所有的订阅(Subscription)
CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
//创建一个新的订阅
Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority);
if (subscriptions == null) {
//如果该事件目前没有订阅列表,创建并加入该订阅
subscriptions = new CopyOnWriteArrayList();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
//如果有订阅列表,检查是否已经加入过
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
- eventType);
}
}
// Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)
// subscriberMethod.method.setAccessible(true);
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
//根据优先级插入订阅
if (i == size || newSubscription.priority > subscriptions.get(i).priority) {
subscriptions.add(i, newSubscription);
break;
}
}
//根据subscriber存储它所有的eventType
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<Class<?>>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
//将这个订阅事件加入到订阅者的订阅事件列表中
subscribedEvents.add(eventType);
//判断sticky;如果为true,从stickyEvents中根据eventType去查找有没有stickyEvent,如果有则立即发布去执行。stickyEvent其实就是我们post时的参数
if (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).
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);
}
}
}
到这里register方法分析完了,大致流程总结一下:
-
找到被注册者类中的所有的订阅方法。
-
遍历订阅方法,找到EventBus中eventType对应的订阅列表,然后根据当前订阅者和订阅方法创建一个新的订阅加入到订阅列表。
-
找到EvnetBus中subscriber订阅的事件列表,将eventType加入到这个事件列表。
所以对于任何一个订阅者,我们可以找到它的订阅事件类型列表,通过这个订阅事件类型,可以找到在订阅者中的订阅函数。
既然register函数分析完了,那么接下来就该分析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) {
unubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
可以看到,首先获取了subscribe函数中根据subscriber存储它的所有eventType保存到List<Class<?>> subscribedTypes
;接着如果存在注册过的type则通过unubscribeByEventType(subscriber, eventType);
循环遍历,完事remove掉所有,这样就完成了所有的unregister功能;至于unubscribeByEventType函数如何实现,具体如下:
/** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
private void unubscribeByEventType(Object subscriber, Class<?> eventType) {
List 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) {
subscription.active = false;
subscriptions.remove(i);
i–;
size–;
}
}
}
}
从上面代码可以看出,原来在register时真正存储EventBus事件的Map是subscriptionsByEventType成员。这里就是循环遍历找出需要unregister的remove掉。至此,整个EventBus的register与unregister函数都分析完毕。
依照前一篇使用来看,进行完register与unregister后剩下的就是post了,那么接下来分析分析post过程,如下:
/** Posts the given event to the event bus. */
public void post(Object event) {
PostingThreadState postingState = 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()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
如上postSticky(Object event)
的实质是post了一个stickyEvents,而真正的post(Object event)
方法里,currentPostingThreadState是一个ThreadLocal类型的,里面存储了PostingThreadState;PostingThreadState包含了一个eventQueue和一些标志位;eventQueue.add(event);
就是把事件放入eventQueue队列,然后while循环遍历eventQueue通过postSingleEvent(eventQueue.remove(0), postingState);语句分发事件;那继续看下这条语句的实现:
private void postSingleEvent(Object event, PostingThreadState postingState) throw
s 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) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
如上代码通过List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
语句传入eventClass得到eventClass对应的事件,包含父类对应的事件和接口对应的事件;接着通过循环遍历eventTypes执行subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
语句;最后如果发现没有对应事件就通过post(new NoSubscriberEvent(this, event));
post一个NoSubscriberEvent事件;接下来看下postSingleEventForEventType函数的实现:
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList 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;
}
如上可以发现,我们在register时扫面class把匹配的方法都存储在了subscriptionsByEventType
,这里通过subscriptions = subscriptionsByEventType.get(eventClass);
语句首先拿到register时扫描的匹配方法;然后判断是否有匹配的方法,如果有就继续遍历每个subscription,依次去调用postToSubscription(subscription, event, postingState.isMainThread);
;
其实这个方法在register的subscribe的checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent)
的方法中也调运过。所以我们继续来分析下这个方法,如下:
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case PostThread:
invokeSubscriber(subscription, event);
break;
case MainThread:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BackgroundThread:
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);
}
}
这个方法传入的三个参数含义分别是:第一个参数就是传入的订阅,第二个参数就是对于的分发事件,第三个参数表明是否在主线程;然后通过subscription.subscriberMethod.threadMode
判断该在哪个线程去执行;这里通过switch分四种情况,如下:
-
case PostThread:直接在当前线程反射调用。
-
case MainThread:如果是(isMainThread)主UI线程则直接调用,否则把当前的方法加入到队列,然后直接通过handler去发送一个消息,通过Handler在主线程执行。
-
case BackgroundThread:如果当前不是主UI线程(!isMainThread)则直接调用,如果是UI线程则创建一个runnable加入到后台的一个队列,最终由Eventbus中的一个线程池去调用。
-
case Async:不论什么线程,直接丢入线程池,也就是将任务加入到后台的一个队列,最终由Eventbus中的一个线程池去调用;线程池与BackgroundThread用的是同一个。
-
default:抛出线程state状态非法异常。
继续分析可以发现mainThreadPoster是继承Handler实现的,其中Looper是MainLooper;invokeSubscriber与asyncPoster都是继承Runnable实现的,其中invokeSubscriber与asyncPoster的enqueue方法实质都差不多,如下:
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
queue.enqueue(pendingPost);
eventBus.getExecutorService().execute(this);
}
可以验证上面说的,invokeSubscriber与asyncPoster的enqueue方法都是扔到了一个线程池中执行。好了,继续看下mainThreadPoster的enqueue方法,如下:
void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {
ster的enqueue方法实质都差不多,如下:
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
queue.enqueue(pendingPost);
eventBus.getExecutorService().execute(this);
}
可以验证上面说的,invokeSubscriber与asyncPoster的enqueue方法都是扔到了一个线程池中执行。好了,继续看下mainThreadPoster的enqueue方法,如下:
void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost);
if (!handlerActive) {