2种思路去读EventBus源码
1.注册 EventBus.getDefault().register(this);
2.发送消息EventBus.getDefault().post();
根据1追到了findSubscriberMethodsWithReflection 根据反射查找订阅者,代码如下里面的内容不解释了,返回的是一个订阅方法的集合。
private ListfindSubscriberMethodsWithReflection(Class> subscriberClass) { List subscriberMethods = new ArrayList (); Class> clazz = subscriberClass; HashSet eventTypesFound = new HashSet (); StringBuilder methodKeyBuilder = new StringBuilder(); while (clazz != null) { String name = clazz.getName(); if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) { // Skip system classes, this just degrades performance break; } // Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again) Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { int modifiers = method.getModifiers(); if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { Class>[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 1) { Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class); if (subscribeAnnotation != null) { String methodName = method.getName(); Class> eventType = parameterTypes[0]; methodKeyBuilder.setLength(0); methodKeyBuilder.append(methodName); methodKeyBuilder.append('>').append(eventType.getName()); String methodKey = methodKeyBuilder.toString(); if (eventTypesFound.add(methodKey)) { // Only add if not already found in a sub class ThreadMode threadMode = subscribeAnnotation.threadMode(); subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode, subscribeAnnotation.priority(), subscribeAnnotation.sticky())); } } } else if (strictMethodVerification) { if (method.isAnnotationPresent(Subscribe.class)) { String methodName = name + "." + method.getName(); throw new EventBusException("@Subscribe method " + methodName + "must have exactly 1 parameter but has " + parameterTypes.length); } } } else if (strictMethodVerification) { if (method.isAnnotationPresent(Subscribe.class)) { String methodName = name + "." + method.getName(); throw new EventBusException(methodName + " is a illegal @Subscribe method: must be public, non-static, and non-abstract"); } } } clazz = clazz.getSuperclass(); } return subscriberMethods; }
然后看调用这个方法的地方
public void register(Object subscriber) { Class> subscriberClass = subscriber.getClass(); // @Subscribe in anonymous classes is invisible to annotation processing, always fall back to reflection boolean forceReflection = subscriberClass.isAnonymousClass(); ListsubscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass, forceReflection); for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } }
接下来咱们继续查看 subscribe(subscriber, subscriberMethod);,如下
划线部分核心代码,到此为止EventBus.getDefault().register(this);大概干了一这样一件事情
通过反射得到观察者(订阅者)的方法,事件和所在的线程
然后将这些参数组装后放入Map中,其中key为事件类型
// Must be called in synchronized block private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { Class> eventType = subscriberMethod.eventType; CopyOnWriteArrayListsubscriptions = subscriptionsByEventType.get(eventType); Subscription newSubscription = new Subscription(subscriber, subscriberMethod); 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); // Got to synchronize to avoid shifted positions when adding/removing concurrently synchronized (subscriptions) { 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; } } } List > 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 ). Set , Object>> entries = stickyEvents.entrySet(); for (Map.Entry , 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); } } }
-----------------------------------------------------------------------------------------------------------------------------
接下来看一下发送消息是怎么实现的
/** Posts the given event to the event bus. */ public void post(Object event) { PostingThreadState postingState = currentPostingThreadState.get(); List
接着看画线部分方法,然后此方法中找到调用的postSingleEventForEventType(Object event, PostingThreadState postingState, Class> eventClass)方法。划线部分是核心代码,头一个划线部分是从map中根据发送事件类型得到的一个类。这个类存储的是订阅的方法,所在的线程,不出意外的话下面应该用的是反射调用订阅的方法。拭目以待
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class> eventClass) { CopyOnWriteArrayListsubscriptions; 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; }
接下来咱们看一下第二个划线部分的代码。里面基本全是反射
/**
*subscription 里面存储的是要调用方法的名字等信息
*event 此事件
*isMainThread boolean 当前发送消息线程是不是UI主线程
*/
private void postToSubscription(Subscription subscription, Object event, boolean。isMainThread) { switch (subscription.subscriberMethod.threadMode) { //当时订阅方法所在的线程 case PostThread: //非主线程 invokeSubscriber(subscription, event); break; case MainThread: //ui主线程 if (isMainThread) { //在主线程直接更新 invokeSubscriber(subscription, event); } else { //通过handler发送消息,防止在自线程中更新UI的误操作 mainThreadPoster.enqueue(subscription, event); } break; case BackgroundThread: if (isMainThread) { //主线程创建runable丢入线程池 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); } }