Android System UI EventBus

前言

在system ui的recents中有大量使用到EventBus的地方,这里会揭示EventBus到底是什么,以及EventBus是如何运作的。
从一个朴素的角度来说,EventBus其实是一个Subscriber-Event的机制,对于Sbuscriber来说,它们的回调函数会在适当的时候被Event所激活。

Start of System UI

system UI的启动flow图:

整个System UI的启动中,我们需要关注的点在:
EventBus: register(sSystemServicesProxy, EVENT_BUS_PRIORITY);

Register EventBus

直接看EventBus的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
EventBus.java
public static EventBus getDefault() {
if (sDefaultBus == null)
synchronized (sLock) {
if (sDefaultBus == null) {
if (DEBUG_TRACE_ALL) {
logWithPid("New EventBus");
}
sDefaultBus = new EventBus(Looper.getMainLooper());
}
}
return sDefaultBus;
}
public void register(Object subscriber, int priority) {
registerSubscriber(subscriber, priority, null);
}
public void register(Object subscriber) {
registerSubscriber(subscriber, DEFAULT_SUBSCRIBER_PRIORITY, null);
}

对于EventBus而言,它是一个单例存在于SystemUI的进程中,通过getDefault方法给出具体的EventBus实例,而通过register方法把对应的suscriber注册到内部。

EventBus还实现了一套进程间的suscriber机制

registerSubscriber

简单看一下register函数的实体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void registerSubscriber(Object subscriber, int priority,
MutableBoolean hasInterprocessEventsChangedOut) {
......
Class<?> subscriberType = subscriber.getClass();
......
// Find all the valid event bus handler methods of the subscriber
MutableBoolean isInterprocessEvent = new MutableBoolean(false);
Method[] methods = subscriberType.getDeclaredMethods();
for (Method m : methods) {
Class<?>[] parameterTypes = m.getParameterTypes();
isInterprocessEvent.value = false;
if (isValidEventBusHandlerMethod(m, parameterTypes, isInterprocessEvent)) {
Class<? extends Event> eventType = (Class<? extends Event>) parameterTypes[0];
......
EventHandlerMethod method = new EventHandlerMethod(m, eventType);
EventHandler handler = new EventHandler(sub, method, priority);
eventTypeHandlers.add(handler);
subscriberMethods.add(method);
sortEventHandlersByPriority(eventTypeHandlers);
......
}
......
}

其中有一句比较敏感的语句:Method[] methods = subscriberType.getDeclaredMethods();
了解过java反射的话,就可以理解这一句代码了,这边是通过class对象拿到对应的methods。
而后,是通过一个for循环去遍历这些methods,并且挨个去isValidEventBusHandlerMethod

isValidEventBusHandlerMethod

这个函数的目的是筛选出当前的subscriber中的函数是否满足EventBus的callback函数签名。
对于EventBus的函数签名,参考EventBus.java

1
2
3
4
5
6
7
8
9
10
/**
* Proguard must also know, and keep, all methods matching this signature.
*
* -keepclassmembers class ** {
* public void onBusEvent(**);
* public void onInterprocessBusEvent(**);
* }
*/
private static final String METHOD_PREFIX = "onBusEvent";
private static final String INTERPROCESS_METHOD_PREFIX = "onInterprocessBusEvent";

因此可以看到,Subscriber的callback函数名都是onBusEvent(进程内),或者onInterprocessBusEvent(进程间)。
有了这样的基础知识,我们再来看看isValidEventBusHandlerMethod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private boolean isValidEventBusHandlerMethod(Method method, Class<?>[] parameterTypes,
MutableBoolean isInterprocessEventOut) {
int modifiers = method.getModifiers();
if (Modifier.isPublic(modifiers) &&
Modifier.isFinal(modifiers) &&
method.getReturnType().equals(Void.TYPE) &&
parameterTypes.length == 1) {
if (EventBus.InterprocessEvent.class.isAssignableFrom(parameterTypes[0]) &&
method.getName().startsWith(INTERPROCESS_METHOD_PREFIX)) {
isInterprocessEventOut.value = true;
return true;
} else if (EventBus.Event.class.isAssignableFrom(parameterTypes[0]) &&
method.getName().startsWith(METHOD_PREFIX)) {
isInterprocessEventOut.value = false;
return true;
} else {
......
}
} else {
......
}
return false;
}

所以对于一个Method是否valid,我们有如下几个判定:

Modifier.isPublic(modifiers):函数是public
Modifier.isFinal(modifiers):函数必须是final
method.getReturnType().equals(Void.TYPE):函数返回值为void
parameterTypes.length == 1:函数的参数数量是1

当通过了这四重考验之后,我们再去检查它的入参类型,以及函数名称:
对于进程间的Subscriber:

EventBus.InterprocessEvent.class.isAssignableFrom(parameterTypes[0])
method.getName().startsWith(INTERPROCESS_METHOD_PREFIX))

对于进程内的Subscriber:

EventBus.Event.class.isAssignableFrom(parameterTypes[0])
method.getName().startsWith(METHOD_PREFIX)

这两步的检查,归结一下其实就是检查入参的类型函数的名称

Add to list

我们假定Suscriber中的onBusEvent已经顺利通过考验,所以我们就来到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void registerSubscriber(Object subscriber, int priority,
MutableBoolean hasInterprocessEventsChangedOut) {
......
Class<? extends Event> eventType = (Class<? extends Event>) parameterTypes[0];
ArrayList<EventHandler> eventTypeHandlers = mEventTypeMap.get(eventType);
if (eventTypeHandlers == null) {
eventTypeHandlers = new ArrayList<>();
mEventTypeMap.put(eventType, eventTypeHandlers);
}
......
EventHandlerMethod method = new EventHandlerMethod(m, eventType);
EventHandler handler = new EventHandler(sub, method, priority);
eventTypeHandlers.add(handler);
subscriberMethods.add(method);
sortEventHandlersByPriority(eventTypeHandlers);
......
}

因此,在mEventTypeMap中维护了一张从class到EventHandler的表

1
private HashMap<Class<? extends Event>, ArrayList<EventHandler>> mEventTypeMap = new HashMap<>();

其中的key,也即Class<? extends Event>,其实是对应的一个一个具体Event。
而value,就是

1
2
EventHandler handler = new EventHandler(sub, method, priority);
eventTypeHandlers.add(handler);

这之中:

Subscriber sub = new Subscriber(subscriber, SystemClock.uptimeMillis());
EventHandlerMethod method = new EventHandlerMethod(m, eventType);

m:Method m
Class<? extends Event> eventType = (Class<? extends Event>) parameterTypes[0];

priority: register的入参

所以,EventHandler handler,它知道谁是subscriber(sub);知道对应的的method以及它的入参(method);了解注册者的优先级(priority)。因此,它可以很轻松地完成transform event。
最后:sortEventHandlersByPriority对EventHandler的list做一次排序

Send EventBus

上面的整个flow已经完成了Event的注册,下面我们来讲述一下event来了之后是如何被送到Subscriber。

EventBus.send

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void send(Event event) {
// Fail immediately if we are being called from the non-main thread
long callingThreadId = Thread.currentThread().getId();
if (callingThreadId != mHandler.getLooper().getThread().getId()) {
throw new RuntimeException("Can not send() a message from a non-main thread.");
}
if (DEBUG_TRACE_ALL) {
logWithPid("send(" + event.getClass().getSimpleName() + ")");
}
// Reset the event's cancelled state
event.requiresPost = false;
event.cancelled = false;
queueEvent(event);
}

首先是thread condition检查,只有main thread才有机会send。
然后是一个function by pass

queueEvent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void queueEvent(final Event event) {
ArrayList<EventHandler> eventHandlers = mEventTypeMap.get(event.getClass());
......
eventHandlers = (ArrayList<EventHandler>) eventHandlers.clone();
int eventHandlerCount = eventHandlers.size();
for (int i = 0; i < eventHandlerCount; i++) {
final EventHandler eventHandler = eventHandlers.get(i);
if (eventHandler.subscriber.getReference() != null) {
if (event.requiresPost) {
mHandler.post(new Runnable() {
@Override
public void run() {
processEvent(eventHandler, event);
}
});
hasPostedEvent = true;
} else {
processEvent(eventHandler, event);
}
}
}
......
}

先通过event type获取到对应的EventHandler list,刚才我们也知道,其实一个EventHandler其实是一个Subscriber。由于之前已经做过了排序,所以这边的list其实是按照优先级高低依次排序了的。

processEvent

1
2
3
4
5
6
private void processEvent(final EventHandler eventHandler, final Event event) {
......
eventHandler.method.invoke(sub, event);
......
}

其实也就是通过sub实例以及event,做了一下method invok,所以就会跑到之前Subscriber的onBusEvent中去了。

小结

其实整个EventBus的实现有很多巧妙的地方。
这里充分利用了函数签名和函数名称的一致性,建立了一套EventBus的Subscriber框架。实现了代码级别的功能解耦,使得同一个事件可以被不同的Subscriber对象所处理,对于Subscriber而言,只需要关注自己关心的那一块即可。