EventBus项目地址为https://github.com/greenrobot/EventBus,clone到本地,主要看EventBus
这个类就可以
关于EventBus的使用可以阅读这篇文章https://blog.csdn.net/Icarus_/article/details/103685194
1、注解定义
EventBus使用注解@Subscribe来标识一个注册方法,RetentionPolicy.RUNTIME表示是运行时注解,ElementType.METHOD表示可注解方法
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
//线程模型
ThreadMode threadMode() default ThreadMode.POSTING;
//是否是粘性事件
boolean sticky() default false;
//订阅事件优先级
int priority() default 0;
}
2、EventBus初始化
EventBus发送事件,注册,反注册都会调用getDefault方法来完成实例的创建。
使用EventBus.getDefault方法获取一个EventBus对象,内部使用的是单例模式,会初始化一些重要的成员变量。单例模式的构造函数一般都是private的,而这里的构造函数是public的,这样设计的原因是EventBus在我们的程序中不仅仅只有一条总线,还有其他的EventBus总线,订阅者可以注册到不同的EventBus上,通过不同的EventBus来发送数据,不同的EventBus发送数据是相互隔离开的,订阅者只会收到注册在该线程上的数据。
public static EventBus getDefault() {
EventBus instance = defaultInstance;
if (instance == null) {
synchronized (EventBus.class) {
instance = EventBus.defaultInstance;
if (instance == null) {
instance = EventBus.defaultInstance = new EventBus();
}
}
}
return instance;
}
public EventBus() {
this(DEFAULT_BUILDER);
}
看一下EventBus类中定义的一些字段:
DEFAULT_BUILDER
,是一个EventBusBuilder,EventBus是通过构造者模式build这个内部类进行对象创建的。
currentPostingThreadState
,是一个ThreadLocal,可以在指定的线程中存储数据。
subscriptionsByEventType
,发送event时,通过这个map找到订阅者。
typesBySubscriber
,当注册和反注册事件的时候,操作这个map。
stickyEvents
,维护粘性事件。
indexCount
,生成的索引。
subscriberMethodFinder
,对已经注解的方法的查找器。
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
......
};
private final SubscriberMethodFinder subscriberMethodFinder;
private final int indexCount;
最重要的三个成员变量poster,poster就是负责线程间调度的
private final Poster mainThreadPoster;
private final BackgroundPoster backgroundPoster;
private final AsyncPoster asyncPoster;
在构造方法中初始化
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
1.mainThreadPoster,跟进去看一下他的初始化,发现返回的是HandlerPoster
这个类,发现他是继承自Handler。handleMessage开启一个循环,从队列中获取数据,然后分发pendingPost,在判断每次分发的时间是否小于最大值,来继续下一次循环或者跳出循环。
public class HandlerPoster extends Handler implements Poster {
//用来放即将执行的post的队列
private final PendingPostQueue queue;
//post事件在HandleMessage存在的最大的时间值
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
//标识handler是否运行起来了
private boolean handlerActive;
......
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
//从队列中获取pendingPost,他维护着一个对象复用池
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = 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;
}
}
......
}
2.backgroundPoster,跟进去看一下,它实现的是runnable,同样的在run方法中循环队列,发送消息。
final class BackgroundPoster implements Runnable, Poster {
.......
@Override
public void run() {
......
while (true) {
PendingPost pendingPost = queue.poll(1000);
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
executorRunning = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);
}
......
}
}
3.asyncPoster,跟进去看一下,也是实现runnable,他的run方法只获取队列中的一个pendingPost进行分发。
class AsyncPoster implements Runnable, Poster {
.......
@Override
public void run() {
PendingPost pendingPost = queue.poll();
if(pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
eventBus.invokeSubscriber(pendingPost);
}
}
3、EventBus注册
3.1 register方法
当EventBus对象创建好之后,就可以调用注册方法register来将某个类注册到这个EventBus对象上。在register方法中,通过subscriberMethodFinder的findSubscriberMethods方法找到注册到EventBus的subscriber类中所有的被@Subscribe注解的订阅事件方法,遍历找到的方法,调用subscribe方法来保存他们。
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
3.2 findSubscriberMethods方法
findSubscriberMethods方法会把找到的监听方法封装成一个SubscriberMethod对象,一个监听方法就对应一个SubscriberMethod对象,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; //方法字符串
}
findSubscriberMethods方法是如何找到一个类中所有被注解的方法的呢。EventBus会将一个类的订阅方法的列表缓存起来,如果有缓存,则会直接返回,没有再通过反射或是编译时生成的代码找到订阅方法列表
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//获取缓存
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
//有则返回
if (subscriberMethods != null) {
return subscriberMethods;
}
//默认为false
if (ignoreGeneratedIndex) {
//通过反射获取订阅方法
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//通过编译时生成的代码获取
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;
}
}
3.2.1 findUsingInfo方法
看一下findUsingInfo方法,获取到findState,得到订阅者及其有关信息,通过循环来遍历,每次遍历完之后都会调用findState方法,依次找寻findState父类。最后getMethodsAndRelease方法返回和释放资源,内部主要就是清空了FindState里面的3个集合。
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//获取到findState它里面存储订阅者一些信息
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中
findState.subscriberMethods.add(subscriberMethod);
}
}
} else {
//如果findState集合为空
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
//返回和释放资源
return getMethodsAndRelease(findState);
}
FindState是用来保存找到的注解过的方法以及他们的状态,看一下他的内部
static class FindState {
//保存所有订阅方法
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
//事件类型为key,订阅方法为value
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
//订阅方法为key,订阅者的class对象为value
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
......
}
接着看一下prepareFindState()方法,他是从FIND_STATE_POOL对象池中找到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();
}
3.2.2 findUsingReflectionInSingleClass方法
接下来看findUsingReflectionInSingleClass方法,它通过反射获取到注册到EventBus类中的所有方法,然后遍历,过滤掉不符合的方法,保留被@Subscribe注解的方法,封装成SubscriberMethod对象保存起来。
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
//获取到注册到EventBus类中的所有方法
// This is faster than getMethods, especially when subscribers are fat classes like Activities
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
......
}
//遍历所有方法
for (Method method : methods) {
int modifiers = method.getModifiers();
//如果是public,且是非静态非抽象方法
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
//是否只有1个参数,因为eventbus只允许订阅方法中的订阅事件是1个
if (parameterTypes.length == 1) {
//获取Subscribe注解
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
//创建SubscriberMethod对象保存起来
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
//获取到线程模式
ThreadMode threadMode = subscribeAnnotation.threadMode();
//将订阅方法添加到findState中
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
}
......
}
......
}
}
看一下里面的checkAdd方法,他是用来判断订阅的方法是否可以添加到订阅方法集合当中。在EventBus中有一个特点,一个订阅者包括他所有的父类或子类,不会有多个方法相同的全部去接受同一个事件,但是可能会出现这样一种情况:子类去订阅该事件,同时父类也会去订阅该事件,这时通过方法签名进行检查
boolean checkAdd(Method method, Class<?> eventType) {
//2级检查:1级,仅具有事件类型的(快速)。2级具有完整签名的。
//通常订阅者没有监听相同事件类型的方法。
//使用在FindState中定义的map,返回之前的value也就是之前的方法
Object existing = anyMethodByEventType.put(eventType, method);
//根据之前的方法是否为空进行下面的操作
if (existing == null) {
return true;
} else {
if (existing instanceof Method) {
//根据方法签名进行检查
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType);
}
}
3.3 Subscribe方法
findSubscriberMethods方法返回列表List< SubscriberMethod>后,在register方法中会遍历这个列表,调用subscribe方法保存起来,在subscribe方法中,首先会创建一个订阅方法SubscriberMethod对应的Subscription对象,然后获取订阅事件对应的Subscription集合,CopyOnWriteArrayList< Subscription>,如果没有则创建,最后将新建的Subscription对象存入集合,这个集合又保存在EventBus最重要的数据结构Map<Class<?>, CopyOnWriteArrayList< Subscription>>对象subscriptionsByEventType中,EventBus的注册主要是完成subscriptionsByEventType对象数据的初始化,这个Map的key为事件类型的Class对象,value为Subscription集合。我们在EventBus中所订阅的事件都会有与之对应的订阅列表,而列表中每个Subscription都会对应一个订阅方法。
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//获取订阅方法对应的事件
Class<?> eventType = subscriberMethod.eventType;
//一个订阅方法subscriberMethod对应一个Subscription
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//获取事件对应的Subscription集合
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
//如果没有集合则创建,并加入subscriptionsByEventType中
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
//如果newSubscription保存过则抛异常
}
}
//获取CopyOnWriteArrayList<Subscription>集合的大小
int size = subscriptions.size();
//遍历subscriptions
for (int i = 0; i <= size; i++) {
//根据优先级将新建的newSubscription加入集合
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<>();
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);
}
}
}
总结一下subscribe
1.首先判断是否注册过该事件
2.然后按照优先级插入到subscriptionsByEventType的value的list中
3.然后在添加到typesBySubscriber的value的list中
4.发布事件,checkPostStickyEventToSubscription
4、EventBus发布事件
由于注册时构建了一个事件类型对应的Subscription集合,发布时获取到该集合然后遍历,调用里面的订阅方法。
看一下post方法,先通过threadLocal获取到PostingThreadState,他就是发送事件的线程状态的封装类,内部有事件队列集合,是否正在发送事件的标志位等
public void post(Object event) {
//通过threadLocal获取到PostingThreadState
PostingThreadState postingState = currentPostingThreadState.get();
//获取到事件的队列
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
//是否正在发送事件
if (!postingState.isPosting) {
//通过looper判断当前是否在主线程
postingState.isMainThread = isMainThread();
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;
}
}
}
post内部调用了postSingleEvent,postSingleEvent内部又调用了postSingleEventForEventType方法,他会获取到发布事件对应的Subscription集合,遍历,调用postToSubscription方法来完成订阅方法的调用。
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
//获取到发布事件对应的Subscription集合
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
try {
//发布事件,调用Subscription对象对应的订阅方法
postToSubscription(subscription, event, postingState.isMainThread);
aborted = postingState.canceled;
}
......
}
return true;
}
return false;
}
postToSubscription里面会根据订阅方法的线程模型来完成在哪个线程执行
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
//posting,直接在当前线程执行
invokeSubscriber(subscription, event);
break;
case MAIN:
//mian,在主线程执行
if (isMainThread) {
//如果在主线程,直接执行
invokeSubscriber(subscription, event);
} else {
//否则切换到主线程,内部是handler完成的
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED:
//将在主线程中调用。该事件总是排队等待以后交付给订阅者,因此对post的调用将立即返回。这为事件处理提供了更严格且更一致的顺序
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
// temporary: technically not correct as poster not decoupled from subscriber
invokeSubscriber(subscription, event);
}
break;
case BACKGROUND:
if (isMainThread) {
//如果当前是主线程,则在EventBus内部线程池中执行
backgroundPoster.enqueue(subscription, event);
} else {
//不在主线程直接调用
invokeSubscriber(subscription, event);
}
break;
case ASYNC:
//在EventBus内部线程池中执行
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
5、EventBus的反注册
注册是给Map<Class<?>, CopyOnWriteArrayList>对象subscriptionsByEventType中添加Subscription集合,那么反注册就是清除掉订阅者subscriber的Subscription
public synchronized void unregister(Object subscriber) {
//获取订阅者订阅事件类型的集合
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
//遍历
for (Class<?> eventType : subscribedTypes) {
//通过事件类型和订阅者找到对应的Subscription并清除
unsubscribeByEventType(subscriber, eventType);
}
//移除订阅者
typesBySubscriber.remove(subscriber);
} else {
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
typesBySubscriber是Map<Object, List<Class<?>>>类型的集合,key是订阅者,value是订阅者订阅事件类型集合。他的数据添加是在注册时完成的,反注册时通过他获取订阅者订阅事件类型集合,然后遍历集合,调用unsubscribeByEventType。
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
List<Subscription> 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--;
}
}
}
}
6、EventBus3.0的索引
6.1、索引的创建
EventBus有一个注解处理器模块EventBusAnnotationProcessor
,此模块下只有一个类EventBusAnnotationProcessor
@SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")
@SupportedOptions(value = {"eventBusIndex", "verbose"})
public class EventBusAnnotationProcessor extends AbstractProcessor {
......
}
@SupportedAnnotationType指定处理的注解为@Subscribe,@SupportedOptions指定处理注解的参数,eventBusIndex和verbose,这两个参数是在build.gradle配置的(配置见eventBus的使用)。
eventBusIndex指定将要生成的EventBus的索引类,verbose是布尔值,编译时是否打印log。注解处理器的配置文件在模块下的META-INF/services/javax.annotation.processing.Processor
里,内容为
org.greenrobot.eventbus.annotationprocessor.EventBusAnnotationProcessor
接下来看EventBusAnnotationProcessor
的process方法是如何处理注解来生成索引文件的
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
//信使,用来编译时打印log
Messager messager = processingEnv.getMessager();
try {
//获取参数eventBusIndex
String index = processingEnv.getOptions().get(OPTION_EVENT_BUS_INDEX);
......
//获取参数verbose
verbose = Boolean.parseBoolean(processingEnv.getOptions().get(OPTION_VERBOSE));
int lastPeriod = index.lastIndexOf('.');
//获取生成索引文件的包名
String indexPackage = lastPeriod != -1 ? index.substring(0, lastPeriod) : null;
......
//收集所有订阅者信息
collectSubscribers(annotations, env, messager);
//检查订阅者,如果不是public的类里面或者里面的事件也不是public则忽略
checkForSubscribersToSkip(messager, indexPackage);
if (!methodsByClass.isEmpty()) {
//创建索引文件
createInfoIndexFile(index);
} else {
......
}
writerRoundDone = true;
}
......
return true;
}
在process方法中,先获取eventBusIndex和verbose参数,然后调用collectSubscribers方法收集所有订阅者信息,检查订阅者,如果不是public的类里面或者里面的事件也不是public则忽略,最后调用createInfoIndexFile生成索引文件。
collectSubscribers收集收集所有订阅者和他内部所有的订阅方法,然后保存在一个ListMap集合methodsByClass中,由于EventBusAnnotationProcessor只处理@Subscribe注解,所以collectSubscribers第一个参数annotations集合中只有一个@Subscribe对应的TypeElement
private void collectSubscribers(Set<? extends TypeElement> annotations, RoundEnvironment env, Messager messager) {
//遍历所有注解类型元素,这里只有注解@Subscribe对应的类型元素
for (TypeElement annotation : annotations) {
//获取所有被@Subscribe注解的元素,也就是订阅方法对应的元素
Set<? extends Element> elements = env.getElementsAnnotatedWith(annotation);
//遍历所有方法对应的elements
for (Element element : elements) {
if (element instanceof ExecutableElement) {
ExecutableElement method = (ExecutableElement) element;
if (checkHasNoErrors(method, messager)) {
//获取订阅方法外部元素,就是所在类的元素类型,如MainActivity
TypeElement classElement = (TypeElement) method.getEnclosingElement();
methodsByClass.putElement(classElement, method);
}
} else {
messager.printMessage(Diagnostic.Kind.ERROR, "@Subscribe is only valid for methods", element);
}
}
}
}
通过collectSubscribers收集到所有的订阅者信息后,就调用createInfoIndexFile创建索引类,使用的是JDK的JavaFileObject来生成Java文件。
6.2、索引的使用
生成索引文件后,就可以使用这个索引文件初始化EventBus实例,因为所有的订阅方法都在索引文件保存起来了,就不需要通过遍历和反射注解来解析订阅方法了。
EventBusBuilder方法创建一个EventBusBuilder对象,然后通过addIndex方法将生成的的索引类加入集合,最后调用InstallDefaultEventBus方法创建EventBus对象。在构造方法中使用subscriberInfoIndexes初始化SubscriberMethodFinder对象。
接下来在注册过程中使用SubscriberMethodFinder查找订阅方法时,会直接使用索引类获取订阅方法。
EventBus(EventBusBuilder builder) {
......
//使用subscriberInfoIndexes初始化subscriberMethodFinder
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
......
}
默认使用findUsingInfo方法查找所有的订阅方法,会调用getSubscriberInfo()通过查找索引文件的方式来获取订阅者所对应的订阅者信息SubscriberInfo对象,如果没有开启索引加上,则会退化为反射查找。
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
//准备一个查找状态的对象,用来跟踪订阅方法查找的过程
FindState findState = prepareFindState();
//设置findState的订阅者类
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//通过索引获取subscriberInfo,该对象中包含所有的订阅方法
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);
}
看getSubscriberInfo()方法
private SubscriberInfo getSubscriberInfo(FindState findState) {
......
if (subscriberInfoIndexes != null) {
//遍历所有索引文件
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
//获取订阅者信息
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
然后就可以通过这个订阅者信息对象获取其中的SubscriberMethod数组,完成订阅方法的查找
@Override
public synchronized SubscriberMethod[] getSubscriberMethods() {
int length = methodInfos.length;
SubscriberMethod[] methods = new SubscriberMethod[length];
for (int i = 0; i < length; i++) {
SubscriberMethodInfo info = methodInfos[i];
methods[i] = createSubscriberMethod(info.methodName, info.eventType, info.threadMode,
info.priority, info.sticky);
}
return methods;
}