临淄网站建设,成品短视频代码推荐大全,wordpress升级4.1,wordpress 分类做导航栏之前写过一篇关于EventBus的文章#xff0c;大家的反馈还不错(EventBus3.0使用详解)#xff0c;如果你还没有使用过EventBus#xff0c;可以去那篇文章看看。当时刚接触EventBus,对它的理解也仅仅是停留在表面#xff0c;写那篇文章也是记录下EventBus的一个简单的使用的过…之前写过一篇关于EventBus的文章大家的反馈还不错(EventBus3.0使用详解)如果你还没有使用过EventBus可以去那篇文章看看。当时刚接触EventBus,对它的理解也仅仅是停留在表面写那篇文章也是记录下EventBus的一个简单的使用的过程而如今随着EventBus在项目中的多次运用个人感觉会用一个框架跟知道它的原理这是两码事所以下定决心写这篇文章来帮助自己更好的理解EventBus。在进入主题之前我们先保持着这样几个疑问EventBus的使用三要素里我们为什么要去定义事件方法并且用到了subscribe()注解 EventBus.getDefault().register(Object)这行代码到底干了什么发送事件的时候又做了哪些操作为什么要在onDestory()做解除绑定的操作...等等(一) 注册: EventBus.getDefault().register(obj)首先调用EventBus的静态getDefault()方法返回一个EventBus对象采用单例实现。// 静态的单例static volatile EventBus defaultInstance;// 默认的EventBusBuilder对象private static final EventBusBuilder DEFAULT_BUILDER new EventBusBuilder();// 使用了单例的双重锁机制public static EventBus getDefault() {if (defaultInstance null) {synchronized (EventBus.class) {if (defaultInstance null) {defaultInstance new EventBus();}}}return defaultInstance;}// 调用带参数的构造方法public EventBus() {this(DEFAULT_BUILDER);}//EventBus(EventBusBuilder builder) {//...subscriptionsByEventType new HashMap();typesBySubscriber new HashMap();stickyEvents new ConcurrentHashMap();mainThreadPoster new HandlerPoster(this, Looper.getMainLooper(), 10);backgroundPoster new BackgroundPoster(this);asyncPoster new AsyncPoster(this);indexCount builder.subscriberInfoIndexes ! null ? builder.subscriberInfoIndexes.size() : 0;subscriberMethodFinder new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex);logSubscriberExceptions builder.logSubscriberExceptions;logNoSubscriberMessages builder.logNoSubscriberMessages;sendSubscriberExceptionEvent builder.sendSubscriberExceptionEvent;sendNoSubscriberEvent builder.sendNoSubscriberEvent;throwSubscriberException builder.throwSubscriberException;eventInheritance builder.eventInheritance;executorService builder.executorService;}在EventBus(builder)构造方法里初始化了一些配置信息。之后调用了EventBus的register(obj)方法这个方法接收的参数类型是Object。这里我们分步骤1和步骤2去看看做了哪些操作。public void register(Object subscriber) {// 通过反射拿到传入的obj的Class对象如果是在MainActivity里做的注册操作// 那subscriber就是MainActivity对象Class subscriberClass subscriber.getClass();// 步骤1List subscriberMethods subscriberMethodFinder.findSubscriberMethods(subscriberClass);// 步骤2synchronized (this) {for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}}}步骤1List subscriberMethods subscriberMethodFinder.findSubscriberMethods(subscriberClass);首先subscriberMethodFinder对象是在EventBus带参数的构造函数里进行初始化的从这个findSubscriberMethods()方法名就可以看出来步骤1的是去获取当前注册的对象里所有的被Subscribe注解的方法集合那这个List集合的对象SubscriberMethod又是什么东东呢 我们去看一下public class SubscriberMethod {final Method method;final ThreadMode threadMode;final Class eventType;final int priority;final boolean sticky;/** Used for efficient comparison */String methodString;public SubscriberMethod(Method method, Class eventType, ThreadMode threadMode, int priority, boolean sticky) {this.method method;this.threadMode threadMode;this.eventType eventType;this.priority priority;this.sticky sticky;}}...看完这个类里定义的信息大概明白了。SubscriberMethod 定义了Method方法名ThreadMode 线程模型eventType 事件的class对象priority是指接收事件的优先级sticky是指是否是粘性事件SubscriberMethod 对这些信息做了一个封装。这些信息在我们处理事件的时候都会用到Subscribe(threadMode ThreadMode.MAIN,sticky true)public void XXX(MessageEvent messageEvent) {...}好的知道了SubscriberMethod 是什么东东后我们直接进入findSubscriberMethods(subscriberClass)方法。List findSubscriberMethods(Class subscriberClass) {// METHOD_CACHE是事先定义了一个缓存Map,以当前的注册对象的Class对象为key,注册的对象里所有的被Subscribe注解的方法集合为valueList subscriberMethods METHOD_CACHE.get(subscriberClass);// 第一次进来的时候缓存里面没有集合subscriberMethods 为nullif (subscriberMethods ! null) {return subscriberMethods;}// ignoreGeneratedIndex是在SubscriberMethodFinder()的构造函数初始化的默认值是 falseif (ignoreGeneratedIndex) {// 通过反射去获取subscriberMethods findUsingReflection(subscriberClass);} else {// 通过apt插件生成的代码。使用subscriber Index生成的SubscriberInfo来获取订阅者的事件处理函数subscriberMethods findUsingInfo(subscriberClass);}if (subscriberMethods.isEmpty()) {throw new EventBusException(Subscriber subscriberClass and its super classes have no public methods with the Subscribe annotation);} else {METHOD_CACHE.put(subscriberClass, subscriberMethods);return subscriberMethods;}}首先是从缓存中获取如果缓存中存在直接返回这里使用缓存有一个 好处比如在MainActivity进行了注册操作多次启动MainActivity就会直接去缓存中拿数据。如果缓存里没有数据就会根据ignoreGeneratedIndex 这个boolean值去调用不同的方法ignoreGeneratedIndex 默认为false。如果此时获取到的方法集合还是空的程序就会抛出异常提醒用户被注册的对象以及他的父类没有被Subscribe注解的public方法(这里插一句很多时候如果打正式包的时候EventBus没有做混淆处理就会抛出该异常因为方法名被混淆处理了EventBus会找不到)把获取到的方法集合存入到缓存中去并且把方法集合return出去。大致的流程就是这样findSubscriberMethods()负责获取注册对象的方法集合优先从缓存中获取缓存中不存在则根据ignoreGeneratedIndex是true或false,如果ignoreGeneratedIndex为true,则调用findUsingReflection()如果为false则调用findUsingInfo()方法去获取方法集合findUsingInfo():private List findUsingInfo(Class subscriberClass) {// 这里采用了享元设计模式FindState findState prepareFindState();// 初始化FindState里的参数findState.initForSubscriber(subscriberClass);while (findState.clazz ! null) {findState.subscriberInfo getSubscriberInfo(findState);if (findState.subscriberInfo ! null) {SubscriberMethod[] array findState.subscriberInfo.getSubscriberMethods();for (SubscriberMethod subscriberMethod : array) {if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {findState.subscriberMethods.add(subscriberMethod);}}} else {findUsingReflectionInSingleClass(findState);}findState.moveToSuperclass();}return getMethodsAndRelease(findState);}// 获取FindState对象采用了享元模式private FindState prepareFindState() {synchronized (FIND_STATE_POOL) {for (int i 0; i POOL_SIZE; i) {FindState state FIND_STATE_POOL[i];if (state ! null) {FIND_STATE_POOL[i] null;return state;}}}return new FindState();}// FindState类定义的信息static class FindState {final List subscriberMethods new ArrayList();final Map anyMethodByEventType new HashMap();final Map subscriberClassByMethodKey new HashMap();final StringBuilder methodKeyBuilder new StringBuilder(128);Class subscriberClass;Class clazz;boolean skipSuperClasses;SubscriberInfo subscriberInfo;void initForSubscriber(Class subscriberClass) {this.subscriberClass clazz subscriberClass;skipSuperClasses false;subscriberInfo null;}........}获取FindState采用了享元模式这里不多说。之后调用了 findState.initForSubscriber(subscriberClass)方法只是为了给FindState对象里的一些信息进行赋值操作。再然后是一个 while循环循环里首先调用getSubscriberInfo(findState)方法点进去看一下发现该方法返回null。这里留一个小疑问getSubscriberInfo()方法什么时候不为null 答案在最后一节的高级用法里private SubscriberInfo getSubscriberInfo(FindState findState) {// findState.subscriberInfo在初始化的时候置为null所以该if 分支不会执行if (findState.subscriberInfo ! null findState.subscriberInfo.getSuperSubscriberInfo() ! null) {SubscriberInfo superclassInfo findState.subscriberInfo.getSuperSubscriberInfo();if (findState.clazz superclassInfo.getSubscriberClass()) {return superclassInfo;}}// subscriberInfoIndexes初始化的时候也是null并没有赋值if (subscriberInfoIndexes ! null) {for (SubscriberInfoIndex index : subscriberInfoIndexes) {SubscriberInfo info index.getSubscriberInfo(findState.clazz);if (info ! null) {return info;}}}return null;}所以findUsingInfo()的while循环里直接走了else分支findUsingReflectionInSingleClass(findState)。也就是说findUsingInfo()方法的主要逻辑是由findUsingReflectionInSingleClass()方法去完成的(默认情况不考虑使用apt)这里有个细节要看一下while (findState.clazz ! null) {findState.subscriberInfo getSubscriberInfo(findState);if (findState.subscriberInfo ! null) {SubscriberMethod[] array findState.subscriberInfo.getSubscriberMethods();for (SubscriberMethod subscriberMethod : array) {if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {findState.subscriberMethods.add(subscriberMethod);}}} else {findUsingReflectionInSingleClass(findState);}findState.moveToSuperclass();}这个while循环什么时候结束呢这是我们第一次看EventBus源码看到这里比较疑惑的地方答案就在这个 findState.moveToSuperclass()里面。void moveToSuperclass() {if (skipSuperClasses) {clazz null;} else {clazz clazz.getSuperclass();String clazzName clazz.getName();/** Skip system classes, this just degrades performance. */if (clazzName.startsWith(java.) || clazzName.startsWith(javax.) || clazzName.startsWith(android.)) {clazz null;}}}我们可以看到去把clazz赋值为它的超类直到没有父类为止才返回clazznull循环也才终止。也就是说 这个while循环保证了获取注解的方法不仅会从当前注册对象里去找也会去从他的父类查找。好了继续分析findUsingReflectionInSingleClass(findState)方法。private void findUsingReflectionInSingleClass(FindState findState) {Method[] methods;try {// 查找注册对象的所有方法注意是所有methods findState.clazz.getDeclaredMethods();} catch (Throwable th) {// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149methods findState.clazz.getMethods();findState.skipSuperClasses true;}// 执行遍历操作for (Method method : methods) {// 获取该方法的修饰符,即public、private等int modifiers method.getModifiers();// 修饰符是public才会走该分支if ((modifiers Modifier.PUBLIC) ! 0 (modifiers MODIFIERS_IGNORE) 0) {// 这里是回去该方法的参数类型StringinClass[] parameterTypes method.getParameterTypes();// 只有一个参数会走该分支if (parameterTypes.length 1) {// 如果该方法被subscribe注解会走该分支Subscribe subscribeAnnotation method.getAnnotation(Subscribe.class);if (subscribeAnnotation ! null) {// 获取传入的对象的ClassClass eventType parameterTypes[0];if (findState.checkAdd(method, eventType)) {// 获取注解上指定的 线程模型ThreadMode threadMode subscribeAnnotation.threadMode();// 往集合中添加数据findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky()));}}} else if (strictMethodVerification method.isAnnotationPresent(Subscribe.class)) {String methodName method.getDeclaringClass().getName() . method.getName();throw new EventBusException(Subscribe method methodName must have exactly 1 parameter but has parameterTypes.length);}} else if (strictMethodVerification method.isAnnotationPresent(Subscribe.class)) {String methodName method.getDeclaringClass().getName() . method.getName();throw new EventBusException(methodName is a illegal Subscribe method: must be public, non-static, and non-abstract);}}}findUsingReflectionInSingleClass()方法首先通过反射去拿到当前注册对象的所有的方法然后去进行遍历并进行第一次过滤只针对修饰符是Public的方法之后进行了第二次过滤判断了方法的参数的个数是不是只有一个如果满足才去进一步的获取被subscribe注解的方法。然后调用findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky()))这行代码new了一个SubscriberMethod()对象传入参数并添加到 findState.subscriberMethods的集合中去.static class FindState {final List subscriberMethods new ArrayList();}之后findUsingInfo()的getMethodsAndRelease(findState)方法回去获取刚刚设置的findState的subscriberMethods集合并把它return出去。代码如下private List getMethodsAndRelease(FindState findState) {// 对subscriberMethods进行了赋值return出去List subscriberMethods new ArrayList(findState.subscriberMethods);// 进行了回收findState.recycle();synchronized (FIND_STATE_POOL) {for (int i 0; i POOL_SIZE; i) {if (FIND_STATE_POOL[i] null) {FIND_STATE_POOL[i] findState;break;}}}return subscriberMethods;}步骤1总结至此以上就是EventBus获取一个注册对象的所有的被subscribe注解的方法的集合的一个过程。该过程的主要方法流程为(1) subscriberMethodFinder.findSubscriberMethods()(2) findUsingInfo()(3) findUsingReflectionInSingleClass()步骤2for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}通过步骤1我们已经拿到了注册对象的所有的被subscribe注解的方法的集合的。现在我们看看subscribe()都做了哪些 操作。我们不妨想想如果我们要去做subscribe()时我们要考虑哪些问题第一个问题是要判断一下这些方法是不是已经注册过该事件了要不要考虑方法名是不是相同的问题。第二个问题是一个注册对象中有多个方法注册了该事件我们该怎么保存这些方法比如说事件类型是String,一个Activity里有两个方法注册了该事件分别是onEvent1和onEvent2那我是不是应该用一个Map集合以事件类型为key把onEvent1和onEvent2放到一个List集合中把该List集合作为value。subscribe()方法private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {// 拿到事件event类型比如是String或者自定义的对象Class eventType subscriberMethod.eventType;// Subscription将注册对象和subscriberMethod 做为参数传入Subscription newSubscription new Subscription(subscriber, subscriberMethod);// subscriptionsByEventType是一个Map集合key是事件类型验证了我上面的猜想CopyOnWriteArrayList subscriptions subscriptionsByEventType.get(eventType);// 如果subscriptions是null,则new出一个CopyOnWriteArrayList并且往Map集合中添加if (subscriptions null) {subscriptions new CopyOnWriteArrayList();subscriptionsByEventType.put(eventType, subscriptions);} else {// 这里做了if语句判断判断一下List集合中是否存在存在就抛异常// 如果不存在怎么没有add操作 保持疑问if (subscriptions.contains(newSubscription)) {throw new EventBusException(Subscriber subscriber.getClass() already registered to event eventType);}}以上的操作验证了我之前的猜想通过if (subscriptions.contains(newSubscription)) 这个if语句判断 是否发生了重复注册注意这里重复注册的含义是 事件类型一致以及方法名也一致。接下来我们看看如果一个注册对象重复注册了事件Event(方法名不能一致)优先级priority是如何设置的int size subscriptions.size();for (int i 0; i size; i) {// 这里判断subscriberMethod的优先级是否是大于集合中的subscriberMethod的优先级如果是把newSubscription插进去// 这也表明了subscription中priority大的在前这样在事件分发时就会先获取。if (i size || subscriberMethod.priority subscriptions.get(i).subscriberMethod.priority) {subscriptions.add(i, newSubscription);break;}}if语句的条件subscriberMethod.priority subscriptions.get(i).subscriberMethod.priority) 保证了subscription中priority大的在前。同时i size 这个条件也保证了priority小的也会添加到subscriptions集合中去紧接着我们看看EventBus是如何处理粘性事件的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);}}}注意以上代码有四行比较重要的注释信息。大致的意思是必须考虑eventType所有子类的现有粘性事件在迭代的过程中所有的event可能会因为大量的sticky events变得低效为了使得查询变得高效应该改变数据结构。isAssignableFrom方法的意思是判断candidateEventType是不是eventType的子类或者子接口如果postSticky()的参数是子Event,那么Subscribe注解方法中的参数是父Event也可以接收到此消息。拿到粘性Event后调用了checkPostStickyEventToSubscription()方法改方法内部方法内部调用了postToSubscription()private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {if (stickyEvent ! null) {// If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)// -- Strange corner case, which we dont take care of here.postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() Looper.myLooper());}}步骤2总结至此EventBus的注册操作已经全部分析完了需要注意的是粘性事件是在subscribe中进行post的(二) 发送事件EventBus.getDefault().post(xxx);普通Eventpublic void post(Object event) {PostingThreadState postingState currentPostingThreadState.get();List eventQueue postingState.eventQueue;// 将Event添加到List集合中去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 {// 遍历这个list集合条件是集合是否是空的while (!eventQueue.isEmpty()) {postSingleEvent(eventQueue.remove(0), postingState);}} finally {postingState.isPosting false;postingState.isMainThread false;}}}首先将当前的 Event添加到eventQueue中去并且while循环处理post每一个Event事件调用的是 postSingleEvent(eventQueue.remove(0), postingState);private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {// 获取Event的Class对象Class eventClass event.getClass();boolean subscriptionFound false;// eventInheritance初始化的时候值为true所以会走该分支if (eventInheritance) {// 获取当前的Event的Class对象的所有父类的Class对象集合优先从缓存里读取。List 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);}......}这里lookupAllEventTypes()方法也是为了获取当前的Event的Class对象的所有父类的Class对象集合优先从缓存里读取。之后是 for循环获取到的Class对象集合调用postSingleEventForEventType()方法。private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass) {CopyOnWriteArrayList subscriptions;synchronized (this) {// subscriptionsByEventType该map是在subscribe()方法中进行了put操作subscriptions subscriptionsByEventType.get(eventClass);}if (subscriptions ! null !subscriptions.isEmpty()) {for (Subscription subscription : subscriptions) {postingState.event event;postingState.subscription subscription;boolean aborted false;try {// 进行for循环并调用了postToSubscription()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;}postSingleEventForEventType()方法主要是获取Event的Class对象所对应的一个List集合集合的对象是Subscription参数。subscriptionsByEventType对象是在subscribe()方法中进行了赋值。for循环CopyOnWriteArrayList集合并调用postToSubscription()线程模型等执行到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 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);}第一个分支线程模型是POST直接调用了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);}}很明显的看到这是基于反射去调用方法invoke方法接收两个参数第一个参数是注册的对象第二个参数是事件的Event。从这里就可以看出来POST并没有去做线程的调度什么的事件处理函数的线程跟发布事件的线程在同一个线程。第二个分支线程模型是MAIN 首先判断了下事件发布的线程是不是主线程如果是执行invokeSubscriber()方法invokeSubscriber()上面已经分析过如果不是主线程执行mainThreadPoster.enqueue(subscription, event)。mainThreadPoster是继承自Handler从这里大概可以猜到这一步是去做线程调度的。我们看一看mainThreadPoster的enqueue做了什么事void enqueue(Subscription subscription, Object event) {// 封装了一个PendIngPostPendingPost pendingPost PendingPost.obtainPendingPost(subscription, event);synchronized (this) {// 将PendIngPost压入队列queue.enqueue(pendingPost);if (!handlerActive) {handlerActive true;// 调用了sendMessage()if (!sendMessage(obtainMessage())) {throw new EventBusException(Could not send handler message);}}}}enqueue() 主要封装了一个PendingPost类并把subscription和event作为参数传进去紧接着把PendingPost压入到队列中去然后发了一条消息sendMessage。熟悉Handler机制的同学知道处理消息是在handleMessage()方法中完成的:public void handleMessage(Message msg) {boolean rescheduled false;try {long started SystemClock.uptimeMillis();while (true) {PendingPost pendingPost queue.poll();if (pendingPost null) {synchronized (this) {// Check again, this time in synchronizedpendingPost queue.poll();if (pendingPost null) {handlerActive false;return;}}}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;}}代码有点多我们主要看一下它接收到消息后是做了什么处理。从队列中取了消息并且调用了eventBus.invokeSubscriber(pendingPost)方法回到EventBus类中。void invokeSubscriber(PendingPost pendingPost) {Object event pendingPost.event;Subscription subscription pendingPost.subscription;PendingPost.releasePendingPost(pendingPost);if (subscription.active) {invokeSubscriber(subscription, event);}}该方法内部还是去调用了invokeSubscriber()方法。分析完线程模型为MAIN 的工作流程不难做出结论当发布事件所在的线程是在主线程时我们不需要做线程调度直接调用反射方法去执行。如果发布事件所在的线程不是在主线程需要使用Handler做线程的调度并最终调用反射方法去执行第三个分支线程模型是BACKGROUND。如果事件发布的线程是在主线程执行backgroundPoster.enqueue(subscription, event)否则执行invokeSubscriber()。backgroundPoster实现了Runable接口:public void enqueue(Subscription subscription, Object event) {PendingPost pendingPost PendingPost.obtainPendingPost(subscription, event);synchronized (this) {queue.enqueue(pendingPost);if (!executorRunning) {executorRunning true;eventBus.getExecutorService().execute(this);}}}将PendingPost对象压入队列然后调用eventBus.getExecutorService().execute(this)交给线程池去进行处理它的处理是在Runnable的run()中。Overridepublic void run() {try {try {while (true) {PendingPost pendingPost queue.poll(1000);if (pendingPost null) {synchronized (this) {// Check again, this time in synchronizedpendingPost 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;}}最重要的还是eventBus.invokeSubscriber(pendingPost)这行代码上面已经分析过。第四个分支线程模型是ASYNC。直接调用 asyncPoster.enqueue(subscription, event)asyncPoster也是实现了Runnable接口里面也是使用的线程池具体的操作就不分析了感兴趣的可以去看一下源码跟上一步操作类似。(三) 高级用法EventBus3.0较之前的版本有了一次改造在3.0之后增加了注解处理器在程序的编译时候就可以根据注解生成相对应的代码相对于之前的直接通过运行时反射大大提高了程序的运行效率但是在3.0默认的还是通过反射去查找用Subscribe标注的方法一般在使用的时候基本都是这个模式。 那我们怎么配置让EventBus使用注解器生成的代码呢在这里我们重点提一下 EventBusBuilder类的boolean ignoreGeneratedIndex;List subscriberInfoIndexes;subscriberInfoIndexes变量可以去使用注解处理器生成的代码。SubscriberInfoIndex 就是一个接口而注解生成器生成的类也是继承的它我们也可以自己去继承它定制自己的需求不需要反射的EventBus。我们再回过头来看一下注册过程的findUsingInfo()方法:private List findUsingInfo(Class subscriberClass) {FindState findState prepareFindState();findState.initForSubscriber(subscriberClass);while (findState.clazz ! null) {findState.subscriberInfo getSubscriberInfo(findState);if (findState.subscriberInfo ! null) {SubscriberMethod[] array findState.subscriberInfo.getSubscriberMethods();for (SubscriberMethod subscriberMethod : array) {if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {findState.subscriberMethods.add(subscriberMethod);}}} else {findUsingReflectionInSingleClass(findState);}findState.moveToSuperclass();}return getMethodsAndRelease(findState);}我们在前面分析的时候直接分析的 findUsingReflectionInSingleClass(findState)方法因为getSubscriberInfo()返回null那什么时候getSubscriberInfo()返回不为null呢 我们具体看看getSubscriberInfo()。private SubscriberInfo getSubscriberInfo(FindState findState) {if (findState.subscriberInfo ! null findState.subscriberInfo.getSuperSubscriberInfo() ! null) {SubscriberInfo superclassInfo findState.subscriberInfo.getSuperSubscriberInfo();if (findState.clazz superclassInfo.getSubscriberClass()) {return superclassInfo;}}// 判断subscriberInfoIndexes 是否为null默认为null,当我们使用apt插件构建代码 的时候可以手动的调用EventBusBuilder的addIndex将subscriberInfoIndexes 进行赋值。if (subscriberInfoIndexes ! null) {for (SubscriberInfoIndex index : subscriberInfoIndexes) {SubscriberInfo info index.getSubscriberInfo(findState.clazz);if (info ! null) {return info;}}}return null;}当我们使用apt插件构建代码 的时候可以手动的调用EventBusBuilder的addIndex()将subscriberInfoIndexes 进行赋值。这样subscriberInfoIndexes 就不会为nullgetSubscriberInfo()方法也就不会为null。findUsingInfo()也就不会调用反射去获取数据从而提高了性能。如何使用新特性SubscriberIndex在gradle文件做以下配置android {defaultConfig {javaCompileOptions {annotationProcessorOptions {arguments [ eventBusIndex : com.example.myapp.MyEventBusIndex ]}}}}dependencies {compile org.greenrobot:eventbus:3.1.1annotationProcessor org.greenrobot:eventbus-annotation-processor:3.1.1}成功构建项目后将为您生成使用eventBusIndex指定的类 。然后在设置EventBus时将其传递给它EventBus.builder().ignoreGeneratedIndex(false).addIndex(new MyEventBusIndex()).installDefaultEventBus();我们回过头看注解器还是很有用的避免使用反射去消耗了性能。总结无论是EventBus还是ButterKnife都使用到了注解处理器这方面的知识还是要多去学习。还有的是对一个框架不仅仅要知道怎么调用它的api还要尽可能的从源码的角度去分析它的实现原理阅读源码也是一个自我提升的一个过程Android的技术讨论Q群947460837