EventBus3 源码解读

基本概念

EventBus是一款针对Android优化的发布/订阅事件总线库。简便了Activities, Fragments, 以及background threads之间的通信,使发送者与订阅者之间有效解耦。
image_1ak28ro9staoi6p139u1bcg3889.png-43.9kB

基本使用

EventBus的使用也极其简单,只需三步即可。

  1. 定义一个事件类型。
    1
    2
    3
    4
    5
    6
     public class MessageEvent {
    public final String message;
    public MessageEvent(String message) {
    this.message = message;
    }
    }
  1. 准备订阅者
    只需给一个public方法添加@Subscribe注解,那么当发布事件时,订阅者就能匹配并接受处理事件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // This method will be called when a MessageEvent is posted
    @Subscribe
    public void onMessageEvent(MessageEvent event){
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
    }

    // This method will be called when a SomeOtherEvent is posted
    @Subscribe
    public void handleSomethingElse(SomeOtherEvent event){
    doSomethingWith(event);
    }

    所有的订阅者都应该在事件总线中被注册。只有被注册的订阅者才能收到事件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Override
    public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
    }

    @Override
    public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
    }
  2. 发布事件
    你可以在代码的任何地方发布事件,所有更当前事件类型匹配的订阅者都可以接收到这个事件。

    1
    EventBus.getDefault().post(new MessageEvent("Hello everyone!"));

EventBus是一个非常小巧的库,但是功能却足够强大,接下来去源码里看看。

源码解读

我们从EventBus.getDefault().register(this);这一行开始,看看getDefault()做了什么?

1
2
3
4
5
6
7
8
9
10
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}

可以看出,保持了一个单例。EventBus的构造方法如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//=================这两个集合很重要,后面经常出现 START========================

//key为事件类型,value为订阅关系列表。用于查询订阅了该事件的所有订阅关系列表,下称事件类型集合
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//key为订阅者,value为订阅者中的事件类型列表。用于查询该订阅者订阅了的事件。下称订阅者集合
private final Map<Object, List<Class<?>>> typesBySubscriber;

//=======================这两个集合很重要,后面经常出现 END==================

//粘性事件,只保留最近一次的事件(相同事件类型只保留一次)
private final Map<Class<?>, Object> stickyEvents;
//存放SubscriberInfo索引
private List<SubscriberInfoIndex> subscriberInfoIndexes;
//事件类型缓存,key为事件类型,value为当前事件类型继承的所有事件类型
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();

//主线程发布者
private final HandlerPoster mainThreadPoster;
//子线程发布者(串行)
private final BackgroundPoster backgroundPoster;
//子线程发布者(另开一个线程)
private final AsyncPoster asyncPoster;
//订阅方法查找器
private final SubscriberMethodFinder subscriberMethodFinder;
//线程池,用于在子线程中发布事件
private final ExecutorService executorService;

private final boolean throwSubscriberException;
private final boolean logSubscriberExceptions;
private final boolean logNoSubscriberMessages;
private final boolean sendSubscriberExceptionEvent;
private final boolean sendNoSubscriberEvent;
private final boolean eventInheritance;

private final int indexCount;

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

//以下通过EventBusBuilder进行赋值
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;
}

代码有点长,看的可能有点晕,从源码可以看出最终构造方法中会传入EventBusBuilder对象进行赋值初始化,EventBusBuilder用来配置信息。构造方法主要就是初始化环境。

注册事件

我们现在就来看看register中的源码。

1
2
3
4
5
6
7
8
9
10
11
12
public void register(Object subscriber) {
//获取Class对象
Class<?> subscriberClass = subscriber.getClass();
//通过方法查找器寻找该订阅者中的订阅方法。
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
//加入到集合中保存
subscribe(subscriber, subscriberMethod);
}
}
}

代码很简练,思路也比较清晰。首先获取订阅者的Class对象,然后通过订阅者方法查找器(SubscriberMethodFinder)查询该订阅者中的订阅方法并返回,最后通过subscribe存入到相关集合中。

在介绍SubscriberMethodFinder之前我们先来了解一下其他几个类。

Subscribe注解

Subscribe用来给订阅方法进行注解,可以指定线程模型,优先级,是否粘性等等。

1
2
3
4
5
6
7
8
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
boolean sticky() default false;
int priority() default 0;
}

ThreadMode(线程模型)

ThreadMode是个枚举类,可以指定四种线程模型。

1
2
3
4
5
6
7
8
9
10
public enum ThreadMode {
//表示在哪个线程发布事件就在哪个线程接收事件
POSTING,
//表示在主线程接收事件
MAIN,
//表示在子线程接收事件
BACKGROUND,
//表示开启一个线程接收事件
ASYNC
}

SubscriberMethod(订阅者方法)

通过类名就可以猜出这个类肯定是用来包装订阅方法的,里面存放了方法、线程模型、事件类型(订阅方法中那个参数类型),优先级、是否粘性等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SubscriberMethod {
final Method method;//订阅方法
final ThreadMode threadMode;//线程模型
final Class<?> eventType;//事件类型(就是订阅方法的参数类型)
final int priority;//优先级
final boolean sticky;//是否粘性

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;
}
//..
//省略部分源码
}

FindState

FindState是一个临时存储订阅方法的类,在查找完毕后就会被回收。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
static class FindState {
//存储订阅方法的集合
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
//根据事件类型存储订阅方法,用来判断是不是该事件已经被添加过了
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
//根据方法名生成的key存储订阅者的类
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
//方法key生成器
final StringBuilder methodKeyBuilder = new StringBuilder(128);

Class<?> subscriberClass;//订阅者的父类
Class<?> clazz;//当前订阅者
boolean skipSuperClasses;//是否跳过父类
SubscriberInfo subscriberInfo;//这个用于注解生成器

//初始化FindState
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}

//回收FindState
void recycle() {
subscriberMethods.clear();
anyMethodByEventType.clear();
subscriberClassByMethodKey.clear();
methodKeyBuilder.setLength(0);
subscriberClass = null;
clazz = null;
skipSuperClasses = false;
subscriberInfo = null;
}
//..
//省略了部分源码
}

Subscription

Subscription表示订阅关系,由订阅者和订阅者方法构成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
final class Subscription {
final Object subscriber;//订阅者
final SubscriberMethod subscriberMethod;//订阅者方法

volatile boolean active;

Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true;
}
//..
//省略了部分源码
}

注册事件

现在我们回过头来看看SubscriberMethodFinder的findSubscriberMethods方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//看看集合中有没有缓存
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}

//是否忽略注解器生成的Index类
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;
}
}

一般如果不引用注解生成器,就会直接走反射查找这个路线。

1
2
3
4
5
6
7
8
9
10
11
12
13
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
//获取一个临时保存订阅信息的FindState类
FindState findState = prepareFindState();
//初始化基本信息(其实就是把subscriberClass赋值给findState.clazz)
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//查找订阅方法
findUsingReflectionInSingleClass(findState);
//定位到父类(就是把父类赋值给findState.clazz,默认跳过系统类)
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);//从FindState类中取出方法集合,然后释放资源。
}

默认会保持4个FindState循环利用,prepareFindState就是取出一个FindState。然后通过findUsingReflectionInSingleClass将订阅方法集合暂时保存在FindState中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
//反射获取方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
//循环遍历所有的方法
for (Method method : methods) {
int modifiers = method.getModifiers();//获取修饰符
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {//必须为public
Class<?>[] parameterTypes = method.getParameterTypes();获取方法的参数类型。
if (parameterTypes.length == 1) {//只能包含一个参数
//获取Subscribe注解
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
//判断是否没有添加过
if (findState.checkAdd(method, eventType)) {
//获取线程模型等信息
ThreadMode threadMode = subscribeAnnotation.threadMode();
//添加到FindState中的subscriberMethods集合类
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
}
//...
//省略了else中的代码
}
}

findUsingReflectionInSingleClass方法主要用于遍历匹配方法,如果满足条件就添加到FindState中的subscriberMethods集合进行保存。既然订阅方法已经遍历完了,那么现在我们回到register方法中。
image_1ak32t2cv1c7e1luh18hprr0146t9.png-24.5kB
可以看出会对每个方法进行遍历然后执行subscribe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//获取事件类型(就是方法里的那个参数类型)
Class<?> eventType = subscriberMethod.eventType;
//用Subscription包装subscriberMethod,可以看出将订阅者与订阅方法给关联了起来。
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);

//看看事件类型集合里是不是存在过之前的事件类型( CopyOnWriteArrayList是线程安全的)
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {//没有当前事件类型的集合
//第一次须初始化列表
subscriptions = new CopyOnWriteArrayList<>();
//subscriptions为空表示之前没有相同的类型,那么现在就塞进去
subscriptionsByEventType.put(eventType, subscriptions);
} else {
//subscriptions不为空说明有相同事件类型的,判断列表里是不是已经包含了,包含就抛出异常
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}


//获取该事件类型的订阅关系列表大小
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) {
//没有就给当前订阅者new个事件列表放进去
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}

//当到该订阅者下的事件列表里
subscribedEvents.add(eventType);

//判断是不是粘性方法
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);
}
}
}

代码有点长,但是逻辑并不复杂,可以看出把订阅方法循环添加到了集合中。然后检查有没有粘性方法,如果有就将最近一次的粘性事件发布即可。

解除事件

接下来看解除事件,为什么不先看发布事件?因为注册和解除是互相呼应的,而且比较简单。趁热看,免得之后又被几个集合给搞懵逼了(说的就是我)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public synchronized void unregister(Object subscriber) {
//根据订阅者查询该订阅者有哪些事件
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
//从事件类型集合中移除
unsubscribeByEventType(subscriber, eventType);
}
//从订阅者集合中移除
typesBySubscriber.remove(subscriber);
} else {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}

我们知道,注册事件时会将订阅者以及订阅事件保存到集合中,那么解除事件毋容置疑,首先去集合中查询有没有,如果有,把它从事件类型集合中移除,然后从订阅者集合中移除。unsubscribeByEventType源码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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--;
}
}
}
}

发布事件

发布事件用ThreadLocal保存了PostingThreadState,PostingThreadState是一个保存事件的类。然后通过循环发送单个事件,可以看出发布事件是串行执行的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/** Posts the given event to the event bus. */
public void post(Object event) {
//PostingThreadState类似于FindState,用于保存要发布的事件,里面有一个事件队列
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;
}
}
}

PostingThreadState的源码如下。

1
2
3
4
5
6
7
8
final static class PostingThreadState {
final List<Object> eventQueue = new ArrayList<Object>();//事件列表
boolean isPosting;//是否正在发布事件
boolean isMainThread;//是否在主线程
Subscription subscription; //订阅关系
Object event; //事件
boolean canceled;//是否已被取消
}

接下来看看postSingleEvent方法。如果可以响应事件继承就获取当前事件类型的所有父类。然后逐个发布事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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);
}
//..
//省略了部分源码
}

可以看出,最终通过postSingleEventForEventType来发布事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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;
}

postToSubscription中即是根据订阅关系发布事件。根据不同的线程模型使用不同发布者进行发布。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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);
}
}

最终通过反射发布事件。我们只来看一下POSTING源码。其他就不赘述了,操作基本大同小异。

1
2
3
4
5
6
7
8
9
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);
}
}

到此为止,整个EventBus工作流程已经梳理完毕。

最后

  • 那个注解生成器是什么鬼?

注解生成器,就是在编译的时候根据注解生成特定的类。就跟自己写的源码一样,执行效率比反射要高很多。
我们在分析subscriberMethodFinder.findSubscriberMethods查找方法时,提到一般只会走反射,所以没有关心通过注解生成器查找的步骤。

1
2
3
4
5
6
7
8
//是否忽略注解器生成的Index类
if (ignoreGeneratedIndex) {
//通过反射查找
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//通过注解生成器生成的类查找
subscriberMethods = findUsingInfo(subscriberClass);
}

现在我们来看下findUsingInfo源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
//初始化FindState
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findState.subscriberInfo = getSubscriberInfo(findState);//获取注解器生成的SubscriberInfo
if (findState.subscriberInfo != null) {
//如果找到了SubscriberInfo就获取方法
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);
}

SubscriberInfo信息如下。

1
2
3
4
5
6
7
8
9
public interface SubscriberInfo {
Class<?> getSubscriberClass();//获取父类

SubscriberMethod[] getSubscriberMethods();//获取订阅方法

SubscriberInfo getSuperSubscriberInfo();//获取父类订阅者信息

boolean shouldCheckSuperclass();
}

getSubscriberInfo用来根据订阅者获取SubscriberInfo。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
}
}
//SubscriberInfoIndex中获取SubscriberInfo
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}

EventBus中注解生成器生成代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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");
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
}
}
}
}

writeIndexLines写入订阅者相关的订阅方法信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void writeIndexLines(BufferedWriter writer, String myPackage) throws IOException {
for (TypeElement subscriberTypeElement : methodsByClass.keySet()) {
if (classesToSkip.contains(subscriberTypeElement)) {
continue;
}

String subscriberClass = getClassString(subscriberTypeElement, myPackage);
if (isVisible(myPackage, subscriberTypeElement)) {
writeLine(writer, 2,
"putIndex(new SimpleSubscriberInfo(" + subscriberClass + ".class,",
"true,", "new SubscriberMethodInfo[] {");
List<ExecutableElement> methods = methodsByClass.get(subscriberTypeElement);
writeCreateSubscriberMethods(writer, methods, "new SubscriberMethodInfo", myPackage);
writer.write(" }));\n\n");
} else {
writer.write(" // Subscriber not visible to index: " + subscriberClass + "\n");
}
}
}

大家只要知道注解生成器是用来干嘛的就行了,关于注解生成器的原理和使用方法,改篇再作深究,有兴趣的可以自行查阅AnnotationProcessor资料。