《Android EventBus的简单使用》中介绍了EventBus的简单使用,从
EventBus.getDefault().register(this);
开始,注意在类中实现相应的onEvent方法:
public void onEventMainThread(ActivityToServiceEvent event) {
String msg = event.getMsg();
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
EventBus.getDefault().post(new ServiceToActivityEvent("MyEvent Send!"));
解除绑定使用:
EventBus.getDefault().unregister(this);
二、源码分析:
从源码中来看上述消息传递是如何实现的,首先类需要register EventBus,在注册之前可以看到使用的getDefault(),估计是个单件模式。
(一)注册过程:
1、EventBus#getDefault:
static volatile EventBus defaultInstance;
// 可以看到是多线程环境下简单的Singleton模式
/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
// 调用构造函数
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
简单的Singleton模式,其主要初始化工作都在构造函数中进行;
2、EventBus#EventBus:
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
public EventBus() {
this(DEFAULT_BUILDER);
}
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
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;
EventBus(EventBusBuilder builder) {
subscriptionsByEventType = new HashMap<Class<?>, CopyOnWriteArrayList<Subscription>>();
typesBySubscriber = new HashMap<Object, List<Class<?>>>();
stickyEvents = new ConcurrentHashMap<Class<?>, Object>();
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
subscriberMethodFinder = new SubscriberMethodFinder(builder.skipMethodVerificationForClasses);
logSubscriberExceptions = builder.logSubscriberExceptions;
logNoSubscriberMessages = builder.logNoSubscriberMessages;
sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
throwSubscriberException = builder.throwSubscriberException;
eventInheritance = builder.eventInheritance;
executorService = builder.executorService;
}
可以看到根据EventBusBuilder进行一些变量的初始化,上述变量在具体用到时再介绍相应的具体含义。
EventBus实例创建之后,接着来看注册过程。
3、EventBus#register:
public void register(Object subscriber) {
register(subscriber, false, 0);
}
public void register(Object subscriber, int priority) {
register(subscriber, false, priority);
}
public void registerSticky(Object subscriber) {
register(subscriber, true, 0);
}
public void registerSticky(Object subscriber, int priority) {
register(subscriber, true, priority);
}
// 最终使用的注册函数
/* @params: subscriber即表示注册EventBus的类对象
* sticky表示消息是否立即发送
* priority表示优先级,优先级越高则会被有限调用*/
private synchronized void register(Object subscriber, boolean sticky, int priority) {
// 这里看到的Method,是通过反射来查找注册类subscriber中的所有相关onEvent函数的
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());
// 对于找到每一个onEvent函数进行响应
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod, sticky, priority);
}
}
前面提供了一系列重载的register函数可供使用,最终调用的都是最后面的同步函数,可以看到在同步函数中,有个List类型的subscriberMethods变量,其工作机制是通过反射查找注册类subscriber中所有相关的onEvent函数,添加到List中,然后再遍历Methods,调用subscribe来响应每一个函数。这也解释了在使用EventBus问什么要定义上述一系列onEvent函数。
4、SubscriberMethodFinder#findSubscriberMethods:
private static final Map<String, List<SubscriberMethod>> methodCache = new HashMap<String, List<SubscriberMethod>>();
// 传入的参数为注册类的Class对象,SubscriberMethod类是对onEvent方法的封装
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
String key = subscriberClass.getName();
List<SubscriberMethod> subscriberMethods;
// 由前面可以看到methodCache是一个HashMap,存储的是注册类名与类中定义的onEvent方法List
synchronized (methodCache) {
subscriberMethods = methodCache.get(key);
}
// 如果已经注册过,则methodCache已经保存了该注册类中的Methods,直接返回;
if (subscriberMethods != null) {
return subscriberMethods;
}
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.")) {
// Skip system classes, this just degrades performance
break;
}
// 通过反射机制,获得类中所有方法Methods
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
String methodName = method.getName();
// @value ON_EVENT_METHOD_NAME = "onEvent";
// 可以看到这里面的就是遍历所有方法,然后判断是都是以onEvent开头,即代码中注册的一系列的onEvent方法
if (methodName.startsWith(ON_EVENT_METHOD_NAME)) {
int modifiers = method.getModifiers();
// 这里判断方法是public类型,且不是static和abstract
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
// 继续限定方法的参数只能为1个
if (parameterTypes.length == 1) {
String modifierString = methodName.substring(ON_EVENT_METHOD_NAME.length());
ThreadMode threadMode;
// 在根据方法名区别出post,mainThread等四种定义的onEvent方法
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 {
if (skipMethodVerificationForClasses.containsKey(clazz)) {
continue;
} else {
throw new EventBusException("Illegal onEvent method, check for typos: " + method);
}
}
Class<?> eventType = parameterTypes[0];
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(methodName);
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
if (eventTypesFound.add(methodKey)) {
// 将检索到的方法组装成SubscriberMethod,添加到List中
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);
}
}
}
// 注意最后一步,可以看到这里不仅扫描当前类,同时还会对其父类进行扫描,查找所有的onEvent方法
clazz = clazz.getSuperclass();
}
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass + " has no public methods called "
+ ON_EVENT_METHOD_NAME);
} else {
synchronized (methodCache) {
methodCache.put(key, subscriberMethods);
}
return subscriberMethods;
}
}
可以看到上面的查找逻辑十分简单,通过反射机制,获取注册类中的所有Methods,然后根据Methods名称,删选出以onEvent开头的,修饰符为public,并且不为static和abstaract的方法,然后再根据名称区分出postThread、mainThread等四种方法类型,统一添加到List中,SubscriberMethod中包含的信息有method对象,方法对应的threadMode(如postThread等),还有onEvent方法中的Event参数类型class;
这里注意代码中最后一步,不仅对当前类进行扫描,同时还会扫描其父类,将所有扫描到的Methods添加进去。
最后EventBus还会使用HashMap(methodCache),将当前类名与扫描到的Methods保存起来,使得重复注册时可以避免扫描直接返回。
接下来,继续回到register中,对每一个method调用subscribe方法。
5、EventBus#subscribe:
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
Class<?> eventType = subscriberMethod.eventType;
// subscriptionsByEventType是一个HashMap,用来存储eventType对应的方法
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority);
// 如果对应subscriptions不存在,则创建
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<Subscription>();
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);
// Subscriptions的添加
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
// 可以看到是根据priority优先级的顺序进行插入的
if (i == size || newSubscription.priority > subscriptions.get(i).priority) {
subscriptions.add(i, newSubscription);
break;
}
}
// 存储subscriber,存储主要用于判断该class是否已经创建
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<Class<?>>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
// 可以看到前面register参数传递中的sticky参数,如果其为true,则直接发送stickyEvent(如果存在的话)
if (sticky) {
Object stickyEvent;
synchronized (stickyEvents) {
stickyEvent = stickyEvents.get(eventType);
}
if (stickyEvent != null) {
// If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
// --> Strange corner case, which we don't take care of here.
postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}
}
subscribe的作用主要是将上面通过反射扫描到的所有onEvent methods添加到EventBus的变量subscriptionsByEventType中来,可以看到同一种eventType(事件类型)的处理函数会被放到一起;将注册类按照priority顺序添加到变量subscriptions中,用以记录哪些类已经注册,哪些类未注册。
至此,register操作已经完成;
下面来分析消息传递过程,即从post开始;
(二)消息传递过程:
1、EventBus#post:
// 可以看到currentPostingThreadState使用ThreadLocal机制
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
/** Posts the given event to the event bus. */
public void post(Object event) {
// 获取当前线程的PostingThreadState
PostingThreadState postingState = currentPostingThreadState.get();
// eventQueue事件队列
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
// isPosting的作用是避免事件被重复post,从后面代码中可以看得出
if (!postingState.isPosting) {
// 根据Looper判断当前线程是否是Main线程
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
// 设置为true,屏蔽重复调度post造成postSingleEvent被多次执行;下一次post会等待当前队列中所有事件被post之后才会继续处理
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
// 可以看到将eventQueue中所有事件event进行处理
while (!eventQueue.isEmpty()) {
// 处理Event的函数
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
上面代码中主要是操作PostingThreadState对象postingState,该对象用来记录当前Event的Post状态,其中有个eventQueue变量用来存储当前线程中POST的Event。postingState通过ThreadLocal来保证线程安全;
代码主要操作逻辑则较为简单,主要的工作是通过Looper判断当前运行线程是否为主线程,然后记录到postingState中;再将当前实践队列eventQueue中的所有event通过postSingleEvent进行处理;
看到上面代码中,每一次post都会将当前eventQueue中的所有event Post出去,为避免eventQueue中的事件未处理完,下一次post操作又会操作eventQueue,因此会通过设置postingState中的isPosting变量来避免该情况,类似于加了锁,等当前post操作完成,将eventQueue中事件处理完,才允许下一个post操作运行。
具体对事件event的处理逻辑在postSingleEvent方法中,如下所示:
2、EventBus#postSingleEvent:
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
// 这里判断eventClass是否是继承类
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);
}
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));
}
}
}
可以看到具体的处理逻辑在postSingleEventForEventType方法中;
3、EventBus#postSingleEventForEventType:
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
// 前面register过程中将处理Event的方法信息存储到subscriptionsByEventType中,这里根据eventClass将其取出
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;
}
上面的代码中用到了前面register过程中(suscribe方法中),将onEvent相关方法信息与其对应的处理EventClass信息存储到一个hashMap——subscriptionsByEventType中,通过key值即eventClass来查找出对应的onEvent方法,然后通过函数postToSubscription来处理。
4、EventBus#postToSubscription:
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
// 根据onEvent方法的threadMode进行分别处理
switch (subscription.subscriberMethod.threadMode) {
case PostThread:
invokeSubscriber(subscription, event);
break;
case MainThread:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BackgroundThread:
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);
}
}
具体的处理逻辑很简单,可以看到是根据onEvent方法的threadMode不同进行分别处理;
1)PostThread则直接处理event;
2)MainThread则如果当前线程为UI线程,则直接进行处理,否则通过Handler机制发送给主线程;
private final de.greenrobot.event.HandlerPoster mainThreadPoster;
final class HandlerPoster extends Handler
3)BackGround则与MainThread进行相反的操作,表示事件处理在子线程中完成;注意backgroundPoster是个Runnable;
private final BackgroundPoster backgroundPoster;
final class BackgroundPoster implements Runnable
4)Async异步执行,则表示直接在子线程中处理事件;
private final AsyncPoster asyncPoster;
class AsyncPoster implements Runnable
AsyncPoster也是一个Runnable;
上面四种处理逻辑则对应了前面四种onEvent四种函数的具体使用环境与使用方法,可以根据具体需求进行选择使用。
5、EventBus#invokeSubscriber:
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);
}
}
具体的处理函数就是通过反射机制,method的invoke来执行具体的操作细节,这些操作细节是我们在onEvent方法中自己定义的;