之前看过EventBus的源码,不是很深入,导致有些模糊,此次仔细阅读了一下,记录笔记,方便以后熟悉。
本篇主要说一下register的过程:

1
2
3
4
5
6
7
8
private synchronized void register(Object subscriber, boolean sticky, int priority) {
//查找subscriber(执行register的类)中注册事件的方法,onEvent开头,参数只允许一个,超过一个将被忽略
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());
for (SubscriberMethod subscriberMethod : subscriberMethods) {
//根据事件类型以及订阅类进行数据处理
subscribe(subscriber, subscriberMethod, sticky, priority);
}
}

findSubscriberMethods这个方法很长,大致要做的事情就是查找出该类以及其父类中声明的所有方法,根据规则(只能public修饰onEvent开头且只有一个参数)筛选出订阅方法,一起看一下吧,具体就在代码中写说明了,删除了部分代码限制篇幅:

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
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//省略部分代码
subscriberMethods = new ArrayList<SubscriberMethod>();
Class<?> clazz = subscriberClass;
HashSet<String> eventTypesFound = new HashSet<String>();
StringBuilder methodKeyBuilder = new StringBuilder();
while (clazz != null) {
String name = clazz.getName();
//忽略系统类
if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
break;
}
//获取该类中声明的所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
String methodName = method.getName();
//是否以onEvent开头
if (methodName.startsWith(ON_EVENT_METHOD_NAME)) {
int modifiers = method.getModifiers();
//修饰符只能以public开头
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
//只能有一个参数
if (parameterTypes.length == 1) {
String modifierString = methodName.substring(ON_EVENT_METHOD_NAME.length());
ThreadMode threadMode;
//获取线程执行方式
if (modifierString.length() == 0) {
threadMode = ThreadMode.PostThread;
} else if (modifierString.equals("MainThread")) {
threadMode = ThreadMode.MainThread;
} else if (modifierString.equals("BackgroundThread")) {
threadMode = ThreadMode.BackgroundThread;
} else if (modifierString.equals("Async")) {
threadMode = ThreadMode.Async;
} else {
//省略部分代码
}
Class<?> eventType = parameterTypes[0];
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(methodName).append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
//检查是否已经添加过
if (eventTypesFound.add(methodKey)) {
// Only add if not already found in a sub class
//添加到列表中
subscriberMethods.add(new SubscriberMethod(method, threadMode, eventType));
}
}
} else if (!skipMethodVerificationForClasses.containsKey(clazz)) {
Log.d(EventBus.TAG, "Skipping method (not public, static or abstract): " + clazz + "."
+ methodName);
}
}
}
//获取父类并且继续查找父类中的订阅方法
clazz = clazz.getSuperclass();
}
//省略部分代码
}

接下来看subscribe(subscriber, subscriberMethod, sticky, priority);这个方法是干啥的,总结来说就是把所有事件类型为eventType的订阅者放入List列表中,并放入Map集合中。然后再根据订阅事件的类构造一个订阅事件列表,用来判断某个类是否已经注册过事件,看一下代码:

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
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
//获取订阅事件中的时间类型
Class<?> eventType = subscriberMethod.eventType;
//根据事件类型查找对应的所有订阅者(由类、方法、优先级组成)
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
//创建一个新的订阅者
Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<Subscription>();
//将订阅者列表放入Map中,后面post的时候会会根据这个eventType来获取该订阅者列表,然后来触发事件
subscriptionsByEventType.put(eventType, subscriptions);
} else {
//不允许重复注册
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
// Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)
// subscriberMethod.method.setAccessible(true);
//根据优先级将新的订阅者插入到已有的订阅者列表中
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || newSubscription.priority > subscriptions.get(i).priority) {
subscriptions.add(i, newSubscription);
break;
}
}
//根据订阅类查找该订阅类中订阅事件类型,isRegister方法会用到此Map,判断是否已经注册过事件
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<Class<?>>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//粘性事件
if (sticky) {
//指定粘性事件是否只触发订阅了当前事件类型的子类的订阅者
if (eventInheritance) {
//stickyEvents中key为事件类名,value为事件类的实例
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries) {
Class<?> candidateEventType = entry.getKey();
//eventType类是否是candidateEventType类的父类
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
//触发事件
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
//获取所有黏性事件并触发
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}

post有两种,一种是在UI线程中,一种是子线程中执行,需要注意的是如果你post的事件类型为A,那么所有订阅过A的超类的事件也同样会被触发,时间原因,源码不分析,后续有时间接着写,记此笔记,方便自己查阅!