先看EventBus的使用,很简单,示例:
//注册
EventBus.getDefault().register(this);
//取消注册
EventBus.getDefault().unregister(this);
//主线程接收消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void doEventBus(MsgEvent event){
//处理逻辑 ...
}
获取EventBus实例:
static volatile EventBus defaultInstance;
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
采用单例模式,获取同一个实例对象
register()方法的实现:
public void register(Object subscriber) {
//首先获得订阅者的class对象
Class<?> subscriberClass = subscriber.getClass();
//通过subscriberMethodFinder来找到订阅者订阅了哪些事件.
//返回一个SubscriberMethod对象的List,类封装了订阅方法信息
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
//订阅
subscribe(subscriber, subscriberMethod);
}
}
}
SubscriberMethod类,订阅方法信息,里面封装了要响应的方法对象(method),将来响应订阅是在哪个线程的(threadMode),订阅的事件类型(eventType),订阅的优先级priority,以及是否接收粘性sticky事件的boolean值.
public class SubscriberMethod {
final Method method;
final ThreadMode threadMode;
final Class<?> eventType;
final int priority;
final boolean sticky;
}
获取订阅方法信息
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//先从缓存中读取
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//是否忽略注解器生成的MyEventBusIndex类
if (ignoreGeneratedIndex) {
//利用反射来获取订阅类中的订阅方法信息
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//从注解器生成的MyEventBusIndex类中获得订阅类的订阅方法信息
subscriberMethods = findUsingInfo(subscriberClass);
}
//在获得subscriberMethods以后,
//如果订阅者中不存在@Subscribe注解并且为public的订阅方法,则会抛出异常。
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else {
//保存到缓存map中
//METHOD_CACHE,是一个map集合,键是class类型
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
着重看通过反射来获取订阅信息:通过反射获取到所有的方法,遍历方法,获取方法的参数类型数组,获取方法的注解信息
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
//FindState 用来做订阅方法的校验和保存
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//通过反射来获得订阅方法信息
findUsingReflectionInSingleClass(findState);
//查找父类的订阅方法
findState.moveToSuperclass();
}
//获取findState中的SubscriberMethod(也就是订阅方法List)并返回
return getMethodsAndRelease(findState);
}
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;
}
//遍历Method
for (Method method : methods) {
int modifiers = method.getModifiers();
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) {
Class<?> eventType = parameterTypes[0];
//校验是否添加该方法
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
//实例化SubscriberMethod对象并添加
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");
}
}
}
EventBus类里有两个非常重要的map集合
// subscriptionsByEventType集合,key是事件类型, value是Subscription对象,包含两个属性,一个是 subscriber 订阅者(反射执行对象),一个SubscriberMethod 注解方法的所有属性参数值
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
// typesBySubscriber集合 key是所有的订阅者,value是所有订阅者里面方法的参数的class
private final Map<Object, List<Class<?>>> typesBySubscriber;
事件分发解析,看发送事件post(event)的实现,其实就是
遍历subscriptionsByEventType,找到符合的方法调用方法的method.invoke() 执行,注意要切换线程。
public void post(Object event) {
//获取当前线程的postingState
PostingThreadState postingState = currentPostingThreadState.get();
//取得当前线程的事件队列
List<Object> eventQueue = postingState.eventQueue;
//将该事件添加到当前的事件队列中等待分发
eventQueue.add(event);
if (!postingState.isPosting) {
//判断是否是在主线程post
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;
}
}
}
取消注册的实现:
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());
}
}
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--;
}
}
}
}
总结一下EventBus的工作原理
订阅逻辑
1.首先用register()方法注册一个订阅者
2.获取该订阅者的所有订阅的方法
3.根据该订阅者的所有订阅的事件类型,将订阅者存入到每个以事件类型为key以所有订阅者为values的map集合中
4.然后将订阅事件添加到以订阅者为key以订阅者所有订阅事件为values的map集合中
5.如果是订阅了粘滞事件的订阅者,从粘滞事件缓存区获取之前发送过的粘滞事件,响应这些粘滞事件。
事件发送逻辑
1.首先获取当前线程的事件队列
2.将要发送的事件添加到事件队列中
3.根据发送事件类型获取所有的订阅者
4.根据响应方法的执行模式,在相应线程通过反射执行订阅者的订阅方法
取消逻辑
1.首先通过unregister方法拿到要取消的订阅者
2.得到该订阅者的所有订阅事件类型
3.遍历事件类型,根据每个事件类型获取到所有的订阅者集合,并从集合中删除该订阅者
4.将订阅者从步骤2的集合中移除