EventBus的使用与分析

2,413 阅读10分钟
  1. 使用过程

    定义事件:
    public class MessageEvent {
        public final String message;
    
        public MessageEvent(String message) {
            this.message = message;
        }
    }
    
    定义事件回调(方法名没有限制):

    在MainActivity中定义事件回调

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void process(MessageEvent event) {
    	Toast.makeText(this, event.message, Toast.LENGTH_LONG).show();
    }
    
    EventBus有5种ThreadMode
    public enum ThreadMode {
    	//在发送事件的线程执行回调
        POSTING,
    	//在主线程执行,如果发送线程是主线程,则同步执行回调;如果不是主线程,则把回调放入主线程消息队列
        MAIN,
    	//直接将回调放入主线程消息队列
        MAIN_ORDERED,
    	//回调在子线程中执行。如果发送线程非子线程,则直接同步执行回调;如果是主线程,则EventBus会新建一个子线程,并把所有的这种类型的事件放到这个线程中执行
        BACKGROUND,
    	//子线程异步执行,一般不是主线程,也不是事件发送线程
        ASYNC
    }
    
    注册和解绑EventBus监听

    如在MainActivity中进行:

    @Override
    protected void onCreate() {
    	super.onCreate();
    	EventBus.getDefault().register(this);
    }
        
    @Override
    protected void onDestroy() {
        super.onDestroy();
    	EventBus.getDefault().unregister(this);
    }
    

    发送事件:

    EventBus.getDefault().post(new MessageEvent("hello"));
    
  2. 其他情况的处理

    1. 发送的事件没有监听器
      //发送了字符串,但是没有对应的字符串类型的事件回调
      EventBus.getDefault().post("hello");
      
      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));
          }
      }
      

      如果配置了EventBusBuilderlogNoSubscriberMessages,会打印日志;

      如果配置了sendNoSubscriberEvent,则会触发一个NoSubscriberEvent事件

    2. 黏性事件

      概念:EventBus会为每个事件类型保存最近一次的事件。当监听者进行注册时,会将缓存的事件发送给它。

      使用场景:跨生命周期或者异步调用等场景可以使用

      举例:从MAinActivity跳转到SecondActivity时,发送一个黏性事件;在SecondActivity注册EventBus时,会触发该黏性事件

      EventBus.getDefault().postSticky(new MessageEvent("ss"));
      Intent it = new Intent(MainActivity.this, SecondActivity.class);
      MainActivity.this.startActivity(it);
      

      SecondActivity中定义黏性事件的回调

      @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
      public void process(MessageEvent e){
         Toast.makeText(this, "sticky", Toast.LENGTH_LONG).show();
      }
      

      在onCreate中向EventBus注册回调,就会触发回调

      EventBus.getDefault().register(this);
      

      原理(黏性事件分发)

      public void postSticky(Object event) {
         synchronized (stickyEvents) {
             //1 每种黏性事件最近的一个实例会被保存
             stickyEvents.put(event.getClass(), event);
         }
          //2 事件也会继续分发
         // Should be posted after it is putted, in case the subscriber wants to remove immediately
         post(event);
      }
      

      注册时的处理逻辑

      private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
          ......
         //注册时,如果回调方法是黏性的,则会将保存的黏性事件分发出去,触发该回调方法
         if (subscriberMethod.sticky) {
             if (eventInheritance) {
                 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);
             }
         }
      }
      
    3. 事件有继承关系
      • 定义了一个回调,事件类型是Object
      @Subscribe(threadMode = ThreadMode.MAIN)
      public void process(Object event) {
      	Toast.makeText(this, event.toString(), Toast.LENGTH_LONG).show();
      }
      

      当发送任意其他类型的事件时,也会触发这个回调,原因在EventBus中有一个eventInheritance变量进行控制,默认为true,会响应该事件及其父类的回调方法

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

      lookupAllEventTypes方法会遍历所有的事件类型,包括其父类

      private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
      	synchronized (eventTypesCache) {
              List<Class<?>> eventTypes = eventTypesCache.get(eventClass);
              if (eventTypes == null) {
                  eventTypes = new ArrayList<>();
                  Class<?> clazz = eventClass;
                  while (clazz != null) {
              	    eventTypes.add(clazz);
                      addInterfaces(eventTypes, clazz.getInterfaces());
                      //事件类型的父类,包括Object
                      clazz = clazz.getSuperclass();
                  }
                  eventTypesCache.put(eventClass, eventTypes);
              }
              return eventTypes;
          }
      }
      

      如果不需要响应该事件的父类的回调,可以将eventInheritance置为false

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          //不使用默认的EventBus实例
          EventBus.builder().eventInheritance(false).installDefaultEventBus();
          EventBus.getDefault().register(this);
      }
      
      • 定义了一个回调,事件类型是SubMessageEvent,继承自MessageEvent
      @Subscribe(threadMode = ThreadMode.MAIN)
      public void process(MessageEvent event) {
          Toast.makeText(this, "Object", Toast.LENGTH_LONG).show();
      }
      
      @Subscribe(threadMode = ThreadMode.MAIN)
      public void processSub(SubMessageEvent event) {
          Toast.makeText(this, "SubMessageEvent", Toast.LENGTH_LONG).show();
      }
      

      发送SubMessageEvent事件,如果eventInheritance为true,会触发上述两个回调,否则只会触发SubMessageEvent的回调

      发送MessageEvent事件,只会触发MessageEvent的回调

    4. 订阅者有继承关系

      SecondActivity继承自MainActivity,触发MessageEvent事件,则SecondActivity能够响应事件回调

      //EventBus.findSubscriberMethods()会调用findUsingReflection()或findUsingInfo()寻找注册类上定义的回调,会遍历循环到父类中使用Subscribe注解的方法
      private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
          FindState findState = prepareFindState();
          findState.initForSubscriber(subscriberClass);
          while (findState.clazz != null) {
              findUsingReflectionInSingleClass(findState);
              //在父类中寻找监听器
              findState.moveToSuperclass();
          }
          return getMethodsAndRelease(findState);
      }
      
      private List<SubscriberMethod> 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);
      }
      
    5. 错误事件

      EventBus提供了AsyncExecutor和ThrowableFailureEvent来捕获异常,并发送异常事件

      过程

      1. 创建一个AsyncExecutor实例,配置了线程池,EventBus实例,及错误事件类型
      2. 执行一个RunnableEx
      3. 捕获运行时异常,并用EventBus发送一个错误事件
       //AsyncExecutor中的execute方法,参数类型是RunnableEx,需实现run方法,该方法会抛出异常
    public void execute(final RunnableEx runnable) {
           threadPool.execute(new Runnable() {
               @Override
               public void run() {
                   try {
                       runnable.run();
                   } catch (Exception e) {
                       Object event;
                       try {
                           event = failureEventConstructor.newInstance(e);
                       } catch (Exception e1) {
                           eventBus.getLogger().log(Level.SEVERE, "Original exception:", 												e);
                           throw new RuntimeException("Could not create failure event", 													e1);
                       }
                       if (event instanceof HasExecutionScope) {
                           ((HasExecutionScope) event).setExecutionScope(scope);
                       }
                       eventBus.post(event);
                   }
               }
           });
       }
       
    

    配合ErrorDialogManager可以在接收到错误事件时,弹一个DialogFragment

       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
           EventBus.getDefault().register(this);
           //配置错误弹窗的标题和内容
           ErrorDialogConfig cfg = new 	
           	ErrorDialogConfig(getResources(),R.string.app_name, R.string.app_name);
           cfg.setEventBus(EventBus.getDefault());
           //创建fragment
           ErrorDialogManager.factory = new ErrorDialogFragmentFactory.Support(cfg);
           //将fragment绑定到activity
           ErrDialogMgr.attachTo(this);
           findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                   AsyncExecutor.create().execute(new AsyncExecutor.RunnableEx() {
                       @Override
                       public void run() throws Exception {
                           Object x = null;
                           //抛出一个空指针异常
                           x.toString();
                       }
                   });
               }
           });
       }
    

    点击按钮会触发空指针异常,EventBus触发一个ThrowableFailureEvent事件,ErrorDialogManager中注册了对应的回调,响应后会显示一个dialog

    注:由于ErrorDialogManagerSupportManagerFragmentHoneycombManagerFragmentonResume()时会调用EventBus.register()方法,但是onEventMainThread(ThrowableFailureEvent event)没有增加@Subscribe(threadMode = ThreadMode.MAIN)注解,会抛异常崩溃。 解决:把这几个类复制出来,并在onEventMainThread方法上增加注解,能够弹窗 这个问题已给EventBus提issue

    1. 调用了注册register(),但是没有定义事件处理回调,即没有使用@Subscribe注解

      会抛出一个异常

      throw new EventBusException("Subscriber " + subscriberClass
                          + " and its super classes have no public methods with the 							@Subscribe annotation");
      
    2. 定义了多个同事件的回调
      @Subscribe(threadMode = ThreadMode.MAIN)
      public void process1(MessageEvent event) {
          Toast.makeText(this, "process111", Toast.LENGTH_LONG).show();
      }
      
      @Subscribe(threadMode = ThreadMode.MAIN)
      public void process2(MessageEvent event) {
          Toast.makeText(this, "process222", Toast.LENGTH_LONG).show();
      }
      

      如果定义了MessageEvent的两个回调方法,当触发MessageEvent事件时,只有第一个方法会执行。

      源码解释:

      EventBus.findUsingInfo()	=>
      FindState.checkAdd()	=>
      FindState.checkAddWithMethodSignature()
      
      private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
      	methodKeyBuilder.setLength(0);
          methodKeyBuilder.append(method.getName());
          methodKeyBuilder.append('>').append(eventType.getName());
      
          String methodKey = methodKeyBuilder.toString();
          Class<?> methodClass = method.getDeclaringClass();
          Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey,
          									methodClass);
          if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
          	// Only add if not already found in a sub class
              return true;
          } else {
              // Revert the put, old class is further down the class hierarchy
              // 如果同一个事件已经定义过回调,则使用之前的,不会用新方法替换
              subscriberClassByMethodKey.put(methodKey, methodClassOld);
              return false;
          }
      }
      

使用注解

运行时通过反射查找注解,会有一些性能损失。EventBus提供了注解处理器,在编译时生成辅助类,提升性能。

使用过程

配置项目的build.gradle:

dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}

配置module的build.gradle:

android {
    
    defaultConfig {
        javaCompileOptions {
            // 注解处理器参数配置
            annotationProcessorOptions {
            // 配置参数名和值
            arguments = [ eventBusIndex : 	
                			'com.example.myapplication.EventBusIndex' ]
            }
        }
    }
}


dependencies {
    // 配置注解处理器
    annotationProcessor  'org.greenrobot:eventbus-annotation-processor:3.1.1'
}

make project之后,在build/source/apt/debug/下可以看到生成的辅助类,可以看到方法有Subscribe注解的类都会把类名与定义的回调方法都保存在SUBSCRIBER_INDEX中

package com.example.myapplication;

import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberMethodInfo;
import org.greenrobot.eventbus.meta.SubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberInfoIndex;

import org.greenrobot.eventbus.ThreadMode;

import java.util.HashMap;
import java.util.Map;

/** This class is generated by EventBus, do not edit. */
public class EventBusIndex implements SubscriberInfoIndex {
    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;

    static {
        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();

        putIndex(new 	SimpleSubscriberInfo(com.example.hero.myapplication.MainActivity.class, true,
                new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("process1", com.example.hero.myapplication.event.MessageEvent.class,
                    ThreadMode.MAIN),
        }));

    }

    private static void putIndex(SubscriberInfo info) {
        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
    }

    @Override
    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
        if (info != null) {
            return info;
        } else {
            return null;
        }
    }
}

添加生成的辅助类,需要在实例化EventBus之前添加

EventBus.builder().addIndex(new EventBusIndex()).installDefaultEventBus();
EventBus.getDefault().register(this);

注解处理器

注解处理器主要有三个步骤

  1. 收集订阅者,遍历每个Subscribe注解,把类和方法存储到一个ListMap中
  2. 过滤订阅者,类和方法需要满足一定的条件
  3. 生成java文件
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
	...
    collectSubscribers(annotations, env, messager);
    checkForSubscribersToSkip(messager, indexPackage);        
    createInfoIndexFile(index);
	...
    return true;
}

收集订阅者

private void collectSubscribers(Set<? extends TypeElement> annotations, 	
							RoundEnvironment env, Messager messager) {
    for (TypeElement annotation : annotations) {
        //遍历注解,获取每个加了注解的方法
        Set<? extends Element> elements = env.getElementsAnnotatedWith(annotation);
        for (Element element : elements) {
            if (element instanceof ExecutableElement) {
                ExecutableElement method = (ExecutableElement) element;
                //方法不是static,必须是public,且只有一个参数
                if (checkHasNoErrors(method, messager)) {
                    //方法所在的类
                    TypeElement classElement = (TypeElement) 
                    			method.getEnclosingElement();
                    //methodsByClass是一个ListMap
                    methodsByClass.putElement(classElement, method);
                }
            } else {
                messager.printMessage(Diagnostic.Kind.ERROR, "@Subscribe is only valid 
                		for methods", element);
            }
        }
    }
}

过滤订阅者

private void checkForSubscribersToSkip(Messager messager, String myPackage) {
    for (TypeElement skipCandidate : methodsByClass.keySet()) {
        TypeElement subscriberClass = skipCandidate;
        while (subscriberClass != null) {
            //类的修饰符是public,则可见
            //类的修饰符是private或protected,则不可见
            //类的修饰符是默认的,则需要生成的辅助类的包名与注解所在类的包名一样
            if (!isVisible(myPackage, subscriberClass)) {
                boolean added = classesToSkip.add(skipCandidate);
                if (added) {
                    String msg;
                    if (subscriberClass.equals(skipCandidate)) {
                        msg = "Falling back to reflection because class is not 
                            public";
                    } else {
                        msg = "Falling back to reflection because " + skipCandidate +
                                    " has a non-public super class";
                    }
                    messager.printMessage(Diagnostic.Kind.NOTE, msg, subscriberClass);
                }
                break;
            }
            List<ExecutableElement> methods = methodsByClass.get(subscriberClass);
            if (methods != null) {
                for (ExecutableElement method : methods) {
                    String skipReason = null;
                    VariableElement param = method.getParameters().get(0);
                    TypeMirror typeMirror = getParamTypeMirror(param, messager);
                    //参数类型校验,DeclaredType表示类或者接口,TypeElement表示类或接口
                    if (!(typeMirror instanceof DeclaredType) ||
                           	!(((DeclaredType) typeMirror).asElement() instanceof 	
                              TypeElement)) {
                        skipReason = "event type cannot be processed";
                    }
                    if (skipReason == null) {
                        TypeElement eventTypeElement = (TypeElement) ((DeclaredType) 								typeMirror).asElement();
                        //类的修饰符是public,则可见
            			//类的修饰符是private或protected,则不可见
           				//类的修饰符是默认的,则需要生成的辅助类的包名与注解所在类的包名一样
                        if (!isVisible(myPackage, eventTypeElement)) {
                            skipReason = "event type is not public";
                        }
                    }
                    if (skipReason != null) {
                        boolean added = classesToSkip.add(skipCandidate);
                        if (added) {
                            String msg = "Falling back to reflection because " + skipReason;
                            if (!subscriberClass.equals(skipCandidate)) {
                                msg += " (found in super class for " + skipCandidate + ")";
                            }
                            messager.printMessage(Diagnostic.Kind.NOTE, msg, param);
                        }
                        break;
                    }
                }
            }
            subscriberClass = getSuperclass(subscriberClass);
        }
    }
}

生成java类

//index:在build.gradle中配置的注解处理器的参数——生成类的文件名,包含包名
private void createInfoIndexFile(String index) {
    BufferedWriter writer = null;
    try {
        JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(index);
        int period = index.lastIndexOf('.');
        //解析包名和类名
        String myPackage = period > 0 ? index.substring(0, period) : null;
        String clazz = index.substring(period + 1);
        writer = new BufferedWriter(sourceFile.openWriter());
        if (myPackage != null) {
            writer.write("package " + myPackage + ";\n\n");
        }
        //写入各种依赖
        writer.write("import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;\n");
        writer.write("import org.greenrobot.eventbus.meta.SubscriberMethodInfo;\n");
        writer.write("import org.greenrobot.eventbus.meta.SubscriberInfo;\n");
        writer.write("import org.greenrobot.eventbus.meta.SubscriberInfoIndex;\n\n");
        writer.write("import org.greenrobot.eventbus.ThreadMode;\n\n");
        writer.write("import java.util.HashMap;\n");
        writer.write("import java.util.Map;\n\n");
        writer.write("/** This class is generated by EventBus, do not edit. */\n");
        writer.write("public class " + clazz + " implements SubscriberInfoIndex {\n");
        //定义静态常量
        writer.write("    private static final Map<Class<?>, SubscriberInfo> 
                     SUBSCRIBER_INDEX;\n\n");
        writer.write("    static {\n");
        writer.write("        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>
                     ();\n\n");
        //调用putIndex方法,把收集的所有类和类中的全部注解方法保存到SUBSCRIBER_INDEX中
        writeIndexLines(writer, myPackage);
        writer.write("    }\n\n");
        //定义添加回调信息的方法
        writer.write("    private static void putIndex(SubscriberInfo info) {\n");
        writer.write("        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);\n");
        writer.write("    }\n\n");
        //实现接口,获取类的订阅信息,包含了所有有注解的方法信息
        writer.write("    @Override\n");
        writer.write("    public SubscriberInfo getSubscriberInfo(Class<?> 
                     subscriberClass) {\n");
        writer.write("        SubscriberInfo info = 
                     SUBSCRIBER_INDEX.get(subscriberClass);\n");
        writer.write("        if (info != null) {\n");
        writer.write("            return info;\n");
        writer.write("        } else {\n");
        writer.write("            return null;\n");
        writer.write("        }\n");
        writer.write("    }\n");
        writer.write("}\n");
    } catch (IOException e) {
        throw new RuntimeException("Could not write source for " + index, e);
    } finally {
        if (writer != null) {
            try {
                writer.close();
            } catch (IOException e) {
                //Silent
            }
         }
    }
}

EventBus对生成类的处理过程

  1. 使用生成的辅助类获取对应类的订阅信息
  2. 将订阅信息中的SubscriberMethodInfo转换为SubscriberMethod
  3. 将每个方法和事件类型添加到对应的Map中
  4. 如果没有注解生成类,则使用反射来获取这个类中每个注解方法的信息
private List<SubscriberMethod> 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);
}

获取类的订阅者信息

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;
        }
    }
    if (subscriberInfoIndexes != null) {
        for (SubscriberInfoIndex index : subscriberInfoIndexes) {
            //从辅助类中获取订阅信息
            SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
            if (info != null) {
                return info;
            }
        }
    }
    return null;
}

简单的性能对比

在一个类中定义多个回调,增加Subscribe注解,分别使用反射和编译时注解,比较register()的耗时:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EventBus.builder().addIndex(new EventBusIndex()).installDefaultEventBus();
        long start = System.currentTimeMillis();
        EventBus.getDefault().register(this);
        Log.i("EventBus","register spend="+(System.currentTimeMillis()- start));
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void process(MessageEvent event) {
        Toast.makeText(this, "process111", Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void process(A event) {
        Toast.makeText(this, "process111", Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void process(B event) {
        Toast.makeText(this, "process111", Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void process(C event) {
        Toast.makeText(this, "process111", Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void process(D event) {
        Toast.makeText(this, "process111", Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void process(E event) {
        Toast.makeText(this, "process111", Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void process(F event) {
        Toast.makeText(this, "process111", Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void process(G event) {
        Toast.makeText(this, "process111", Toast.LENGTH_LONG).show();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void process(H event) {
        Toast.makeText(this, "process111", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
}

多次运行结果:

  1. 使用编译时注解基本只有方法调用的耗时,非常少,日志显示为0~1ms
  2. 运行时反射,耗时一般在3~4ms