Eventbus3.0源码解析2

在移动开发中,通信(进程间,线程间,组件间)是非常频繁的需求,最经常用的一种方式就是通过接口实现的方式来进行不同组件间的通信,还可以用广播发送接收的方式,但是如果一个应用内很多涉及通信的需求,就会导致代码看起来非常的乱,并且代码耦合度高,所以就有了第三方框架来统一管理。本文就是分析一下这方面用户量比较多的一个库EventBus的使用方法和原理分析。本文如果有什么不对的地方请指出,我只是按照我自己的思路分析的。github传送门:https://github.com/greenrobot/EventBus

网上也有很多对EventBus源码解析的博客,但是我看了大部分都是针对以前的版本,所以我就专门分析最新版3.0的源码了,如果有对以前的版本感兴趣的请参考:Android解耦库EventBus的使用和源码分析

使用方法

看源码之前首先看看是怎么用的,才知道从哪里开始分析是吧。使用前先引用:

1
compile 'org.greenrobot:eventbus:3.0.0'

 

用法就参考下面这个简单的Demo

需求:不同线程间的通信(子线程执行一个任务,执行完毕通知主线程更新ui)
效果图:

代码:
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
public class MainActivity extends AppCompatActivity {
Button button;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.bt_start);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startTask();
}
});
//注册Eventbus,同一个对象只能注册一次,重复注册会抛异常
EventBus.getDefault().register(this);
}
 
/**
* 接受监听的方法(方法名可以随便写,这也是3.0改进的地方)
* 通过注解的方式来实现
* 参数threadMode有4个值:ThreadMode.POSTING,ThreadMode.MAIN,ThreadMode.ASYNC,ThreadMode.BACKGROUND默认是ThreadMode.POSTING
* 这4个值的含义分别为:
* ThreadMode.POSTING:该事件在哪个线程发布出来的,该方法就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。使用这个方法时,在该方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。
* ThreadMode.MAIN:不论事件是在哪个线程中发布出来的,该方法都会在UI线程中执行,接收事件就会在UI线程中运行,这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在该方法中是不能执行耗时操作的。
* ThreadMode.ASYNC:无论事件在哪个线程发布,都会创建新的子线程在执行。
* ThreadMode.BACKGROUND:如果事件是在UI线程中发布出来的,那么该方法就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么该方法直接在该子线程中执行。
* @param object
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void updateUi(Object object) {
button.setText("Complete");
button.setBackgroundColor(Color.GREEN);
}
 
@Override
protected void onDestroy() {
super.onDestroy();
//解除注册Eventbus
EventBus.getDefault().unregister(this);
}
 
/**
* 开启子线程执行任务
*/
private void startTask() {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
SystemClock.sleep(500);
//发送通知(发送通知的参数类型要和接收通知的参数类型一致才能成功回调)
EventBus.getDefault().post(new Object());
}
}
}).start();
}
}

好了,使用方法大致介绍完毕。下面开始源码分析,到底EventBus是怎么实现的呢?

源码分析

首先我们就从register函数看起吧,顺藤摸瓜的道理

1
2
3
4
5
6
7
8
9
10
11
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
//通过subscriberMethodFinder.findSubscriberMethods(subscriberClass)找到注册的函数集合
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
//分别注册每个函数
subscribe(subscriber, subscriberMethod);
}
}
}

 

下面我们就看看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) {
//先检查缓存中是否已经存在,如果存在的话直接从缓存中取出并返回
//METHOD_CACHE是一个已subscriberClass为key的map集合
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//缓存中不存在,如果忽略...这个参数不知道什么意思,默认是false,所以会走else里面
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//到这里,又调用了findUsingInfo方法
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;
}
}

 

这源码读起来真顺畅,一点疑惑都没有,那么继续跟进findUsingInfo函数

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 List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
//这个FindState简单的看了下,就是一个好像搜索引擎之类的东西,一共初始化了4个,这里就取出了一个
//FindState里面维护了一大堆东西,就不一一介绍了
FindState findState = prepareFindState();
//把注册类跟findState关联起来
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//获取注册类的信息SubscriberInfo,第一次为null,所以走else
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) {
//遍历找到的函数集合,并添加到findState.subscriberMethods中
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();
}
//释放findState这个对象,并取出返回值返回
return getMethodsAndRelease(findState);
}

 

关键部分来了,追踪了半天,终于要看到幕后黑手了,就是findUsingReflectionInSingleClass函数

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
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// This is faster than getMethods, especially when subscribers are fat classes like Activities
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
//通过反射获取注册类的所有方法
for (Method method : methods) {
int modifiers = method.getModifiers();
//方法必须是public修饰的
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
//获取subscribe注解的方法,并获取方法的第一个参数类型
Class<?> 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");
}
}
}

 

好了,现在知道它查找注册函数的原理了,然后回到register函数,下面还要看一个方法,就是subscribe(subscriber, subscriberMethod);

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
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
//以eventType为key,subscriptions为value保存到subscriptionsByEventType中
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
//第一次为null
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
//第一次size=0
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) {
subscribedEvents = new ArrayList<>();
//以subscriber为key,subscribedEvents为value保存到typesBySubscriber中
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);
}
}
}

 

可以看到EventBus类维护了两个Map集合,一个是以eventType为key,subscriptions为value保存到subscriptionsByEventType中,另外一个是以subscriber为key,subscribedEvents为value保存到typesBySubscriber
到此为止,register方法分析完毕,然后我们只需看看post方法就真相大白了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/** Posts the given event to the event bus. */
public void post(Object event) {
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;
}
}
}

 

继续,跳入postSingleEvent函数

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
//eventInheritance默认是false,看else
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 {
//看postSingleEventForEventType
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
//没有找对对应的注册函数
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
 
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
//刚才register的时候有看到
// EventBus类维护了两个Map集合,
// 一个是以eventType为key,subscriptions为value保存到`subscriptionsByEventType`中
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;
}
 
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
//直接在当前线程调用方法
invokeSubscriber(subscription, event);
break;
case MAIN:
//如果是主线程就在主线程调用,如果是子线程就post到主线程
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BACKGROUND:
//如果是主线程就post到后台线程线程,如果是子线程就在当前线程调用
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);
}
}

 

好了,分析完毕,我发现前面推荐的那篇博客介绍的有错误。BACKGROUND:如果是主线程就post到后台线程线程,如果是子线程就在当前线程调用。ASYNC:创建新的子线程。他说反了…欢迎大家纠错。

posted @ 2017-08-09 14:57  天涯海角路  阅读(107)  评论(0)    收藏  举报