2种思路去读EventBus源码
1.注册 EventBus.getDefault().register(this);
2.发送消息EventBus.getDefault().post();
根据1追到了findSubscriberMethodsWithReflection 根据反射查找订阅者,代码如下里面的内容不解释了,返回的是一个订阅方法的集合。
private List<SubscriberMethod> findSubscriberMethodsWithReflection(Class<?> subscriberClass) { List<SubscriberMethod> subscriberMethods = new ArrayList<SubscriberMethod>(); Class<?> clazz = subscriberClass; HashSet<String> eventTypesFound = new HashSet<String>(); 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(); List<SubscriberMethod> subscriberMethods = 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; CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType); Subscription newSubscription = new Subscription(subscriber, subscriberMethod); if (subscriptions == null) { subscriptions = new CopyOnWriteArrayList<Subscription>(); 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<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber); if (subscribedEvents == null) { subscribedEvents = new ArrayList<Class<?>>(); 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<Class>). 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); } } }
-----------------------------------------------------------------------------------------------------------------------------
接下来看一下发送消息是怎么实现的
/** Posts the given event to the event bus. */ public void post(Object event) { PostingThreadState postingState = currentPostingThreadState.get(); List<Object> 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; } } }
接着看画线部分方法,然后此方法中找到调用的postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass)方法。划线部分是核心代码,头一个划线部分是从map中根据发送事件类型得到的一个类。这个类存储的是订阅的方法,所在的线程,不出意外的话下面应该用的是反射调用订阅的方法。拭目以待
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; }
接下来咱们看一下第二个划线部分的代码。里面基本全是反射
/**
*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); } }