使用篇
1.添加依赖库
compile 'org.greenrobot:eventbus:3.0.0'
2.注册、订阅、取消订阅事件
EventBus.getDefault().register(obj);//注册
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)//sticky:true为黏性事件,false为一般事件
public void onMessageReceive(Object obj) {//订阅
//onMessageReceive这个方法名可以任意取,obj为发布者发布的事件类型
//省略...
}
EventBus.getDefault().unregister(obj);//取消订阅
3.事件发布者发布事件
EventBus.getDefault().post(obj);//一般事件
EventBus.getDefault().postSticky(obj);//黏性事件
4.混淆
-keepattributes *Annotation*
-keepclassmembers class **{
@org.greenrobot.eventbus.Suscribe<methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode{*;}
#only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent{
<init>(java.lang.Throwable);
}
源码解析篇
当我们使用EventBus时,首先会调用EventBus.getDefault()来获取EventBus实例,下面看getDefault方法:
EventBus#getDefault
static volatile EventBus defaultInstance;//EventBus实例
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
很明显,这是采用DCL双重检查的单例设计模式,下面看它的构造方法:
//EventBus的建造者模式builder,通过它为EventBus设置各种默认属性
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
public EventBus() {
this(DEFAULT_BUILDER);//DEFAULT_BUILDER为EventBus的建造者模式builder
}
EventBus(EventBusBuilder builder) {
//private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//订阅者与订阅事件的集合,注意:一个订阅者可以订阅多个订阅事件
//因此是一个订阅者和若干个订阅事件
subscriptionsByEventType = new HashMap<>();
//private final Map<Object, List<Class<?>>> typesBySubscriber;
//订阅事件类型,根据订阅对象轻松找到订阅者类,用于取消订阅时
typesBySubscriber = new HashMap<>();
//private final Map<Class<?>, Object> stickyEvents;
//订阅者和订阅事件,黏性事件
stickyEvents = new ConcurrentHashMap<>();
//这是一个handler,用于排队发布事件与取出发布事件来消费
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
//后台线程
backgroundPoster = new BackgroundPoster(this);
//异步线程
asyncPoster = new AsyncPoster(this);
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
//private final SubscriberMethodFinder subscriberMethodFinder;
//订阅者方法的查找类,这个类很重要,用于查找订阅者的订阅方法(集合)
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
//省略...
}
通过构造方法,它调用了this(DEFAULT_BUILDER),这里的DEFAULT_BUILDER就是EventBusBuilder,可以看出,它通过建造者模式对EventBus进行各种配置。这里就不贴EventBusBuilder的代码了,可自行阅读EventBusBuilder源码。
在获取了EventBus实例后,会调用注册方法,把订阅者注册到EventBus中。下面看这个注册方法:
EventBus#register
public void register(Object subscriber) {
//获取订阅者类class
Class<?> subscriberClass = subscriber.getClass();
//通过订阅者方法查找类的查找方法,返回订阅方法SubscriberMethod集合
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {//遍历订阅方法集合
subscribe(subscriber, subscriberMethod);//对每个订阅者进行注册
}
}
}
通过阅读register源码,我们不难看出它整体思路:通过订阅者class,获取该订阅者里面所有的订阅方法,然后开启同步锁并遍历订阅方法,对每一个订阅方法进行注册操作。
这里要补充说明一下SubscriberMethod(订阅方法)里面的几个属性:
public class SubscriberMethod {
final Method method;//订阅者定义的方法
//ThreadMode为枚举类型,取值如下:POSTING,MAIN,BACKGROUND,ASYNC
final ThreadMode threadMode;//订阅方法工作的线程
final Class<?> eventType;//EventBus发布(post)的事件类型,即订阅方法接收的数据类型
final int priority;//订阅方法优先级
final boolean sticky;//是否为黏性方法
//其余部分省略...
}
下面看看订阅者方法查找类究竟是如何查找订阅方法的?
SubscriberMethodFinder#findSubscriberMethods
//METHOD_CACHE是缓存,key是订阅者,value是订阅方法集合
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
//是否忽略注解器生成的XxxEventBus
private final boolean ignoreGeneratedIndex;
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//从缓存中获取订阅者类class的订阅方法
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {//一旦在缓存中找到,就不再查找,直接返回订阅方法集合
return subscriberMethods;
}
//ignoreGeneratedIndex默认为false,也可以通过EventBusBuilder来设置。
//这里因为我们是通过EventBus.getDefault()方法来获取的实例
//所以ignoreGeneratedIndex是默认false的情况,即执行else情况
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
subscriberMethods = findUsingInfo(subscriberClass);
}
if (subscriberMethods.isEmpty()) {//如果在订阅者中没有找到订阅方法,则抛未找到异常
throw new EventBusException("Subscriber " + subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else {
//把订阅者类class与订阅方法集合存入缓存,方便下次调用不再继续查找,直接缓存读取
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
阅读上面源码可知:首先从缓存METHOD_CACHE中查找订阅方法集合,找到立即返回,后面不会再执行;否则,根据ignoreGeneratedIndex是否为true,执行查找获取对应的订阅方法集合;接着对找到的订阅方法集合判空,如果是空,则抛出异常,不为空时,则把订阅者与对应的订阅方法集合存入缓存,方便下次调用不需重新查找,最后返回订阅方法集合。
从上面源码可知,查找订阅方法由findUsingInfo方法执行,下面看该方法:
SubscriberMethodFinder#findUsingInfo
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();//返回FindState实例
findState.initForSubscriber(subscriberClass);//初始化FindState
while (findState.clazz != null) {//当findState.clazz == null时结束循环
//获取订阅者信息,并赋值给findState.subscriberInfo
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) {//对findState.subscriberInfo进行判空
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();
}
return getMethodsAndRelease(findState);
}
观察findUsingInfo方法,首先执行的是prepareFindState方法,返回查找状态类FindState的实例。
这里需补充一下说明FindState,它是SubscriberMethodFinder的静态内部类:
SubscriberMethodFinder静态内部类FindState
static class FindState {
//订阅方法
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
Class<?> subscriberClass;//订阅者class
Class<?> clazz;//订阅者class
boolean skipSuperClasses;//是否跳过检查父类class
SubscriberInfo subscriberInfo;//订阅者信息
//其他略...
}
下面看prepareFindState方法是如何返回查找状态类FindState实例的:
SubscriberMethodFinder#prepareFindState
private static final int POOL_SIZE = 4;
//定义一个容量为4的查找状态数组
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
private FindState prepareFindState() {
synchronized (FIND_STATE_POOL) {//以数组作为同步锁
for (int i = 0; i < POOL_SIZE; i++) {//对数组进行遍历
FindState state = FIND_STATE_POOL[i];
if (state != null) {//一旦发现查找状态不为空,立即返回,并把数组内查找状态置为空
FIND_STATE_POOL[i] = null;
return state;
}
}
}
return new FindState();//在数组内的查找状态均为空时,新建一个查找状态实例返回
}
在获得FindState实例后,调用initForSubscriber初始化该状态:
FindState#initForSubscriber
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;//把订阅者class赋值给subscriberClass和clazz
skipSuperClasses = false;
subscriberInfo = null;
}
之后在findState.clazz不为空的条件下循环,直到findState.clazz为空结束循环,并通过调用getMethodsAndRelease方法返回List<SubscriberMethod>。
先看循环体内逻辑,调用getSubscriberInfo方法,返回查找状态的订阅者信息findState.subscriberInfo,依据该信息是否为空,执行相应的操作。还是看看getSubscriberInfo方法:
SubscriberMethodFinder#getSubscriberInfo
private List<SubscriberInfoIndex> subscriberInfoIndexes;
private SubscriberInfo getSubscriberInfo(FindState findState) {
//通过FindState#initForSubscriber方法 => subscriberInfo = null可知,不会执行if语句块
if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
}
//subscriberInfoIndexes到目前为止,均未被赋值,因此也是null,因此也不会执行if语句块
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;//有上面可知,最终执行返回null
}
该方法,首先是判空:在传入的查找状态findState中存储的订阅信息不为空且其父类定阅信息不为空的条件下,获取其父类订阅信息superclassInfo,然后在传入的订阅信息与其父类订阅信息一致的情况下,返回该父类订阅信息;第二次判空:当subscriberInfoIndexes不为空时,对数组subscriberInfoIndexes进行遍历,在订阅者信息不为空时返回,不在往下执行;在两次判空均为null时,直接返回null(订阅者信息)。
对于getSubscriberInfo方法,首先传入的findState就是上面通过初始化之后的状态,即findState.subscriberInfo为空,接着由EventBus的构造方法subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex)可知,subscriberInfoIndexes也是空,所以最终返回的订阅者信息是空,所以findUsingInfo方法的循环体里面的判断语句执行else语句:findUsingReflectionInSingleClass(findState)。
SubscriberMethodFinder#findUsingReflectionInSingleClass
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
//通过反射获取订阅者所有方法(public + private)
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
//通过反射获取订阅者所有方法(public)
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
for (Method method : methods) {//遍历所有的方法
int modifiers = method.getModifiers();//获取方法的修饰符
//只有方法修饰符是public且不是abstract或static才能进入执行if语句块
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
//获取方法的参数类型数组
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {//只有当方法的参数为一个时,才能执行if语句块
//满足上面所有条件的方法获取方法注解@Subscribe
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {//当获取的注解不是空时,此方法才是订阅者类的订阅方法
//获取方法参数类型,即post(Object event)的event类型
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {//当订阅者与订阅方添加成功后
ThreadMode threadMode = subscribeAnnotation.threadMode();
//把订阅方法添加到findState.subscriberMethods里面
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
//默认情况下strictMethodVerification=false,因此if语句块不会执行。
} 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);
}
//默认情况下strictMethodVerification=false,因此if语句块不会执行。
} 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");
}
}
}
通过阅读findUsingReflectionInSingleClass源码,我们知道:首先通过反射获取订阅者类的所有方法,然后对方法进行遍历,只有当方法修饰符为public、方法参数只有一个且该方法存在@Subscribe注解时,该方法才是订阅者类的订阅方法,接着获取@Subscribe注解实例(不为空时),把订阅方法(包括方法,订阅者,线程模式,优先级,是否黏性事件)添加到findState.subscriberMethods里面。
分析完findUsingReflectionInSingleClass源码,接着就是findState.moveToSuperclass:
FindState#moveToSuperclass
void moveToSuperclass() {
if (skipSuperClasses) {//跳过父类方法检测
clazz = null;
} else {//检测父类方法时
clazz = clazz.getSuperclass();
String clazzName = clazz.getName();
/** Skip system classes, this just degrades performance. */
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
clazz = null;
}
}
}
从这段源码可知:当skipSuperClasses为true,或者父类方法是系统方法时,置clazz为null,其他时候置clazz为clazz.getSuperclass()。
最后就是跳出循环体,通过调用getMethodsAndRelease方法,返回订阅方法集合了。
SubscriberMethodFinder#getMethodsAndRelease
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
findState.recycle();
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState;
break;
}
}
}
return subscriberMethods;
}
这一段源码很简单,就是通过findState.subscriberMethods新建一个订阅者方法集合并最终返回,接着重置findState,并把之前的findState设置到FIND_STATE_POOL数组中。
分析完查找订阅者的订阅方法之后,回到EventBus的register方法,采用同步锁并遍历订阅方法集合,对找到的每一个订阅方法与订阅者进行注册操作。
EventBus#subscribe
// Must be called in synchronized block必须在同步代码块中调用
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//首先获取EventBus的post数据类型
Class<?> eventType = subscriberMethod.eventType;
//创建一个订阅事件(包括订阅者和订阅方法)
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType
//以发布的数据类型为key,获取线程安全的发布事件集合
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {//当集合为空时,new一个,并把发布数据类型与发布事件存入缓存
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {//当集合不为空,且集合内包含该发布事件,则抛异常。
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
//这部分代码是把订阅事件按优先级插入集合或集合末尾插入
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;
}
}
//Map<Object, List<Class<?>>> typesBySubscriber
//从缓存中根据key(订阅者)取出value(发布事件类型)
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {//如果集合为空,创建一个
subscribedEvents = new ArrayList<>();
//把订阅者与发布的订阅事件集合存入缓存
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);//把发布的订阅事件存入集合
if (subscriberMethod.sticky) {//根据是否黏性事件
if (eventInheritance) {//默认是true,事件是否有继承性
// 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 {
//Map<Class<?>, Object> stickyEvents
//缓存中根据发布的事件类型class,取出原发布事件
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
剖析该方法前,先补充说明一下订阅事件Subscription这个类:
final class Subscription {
final Object subscriber;//订阅者类
final SubscriberMethod subscriberMethod;//订阅方法(方法,线程,发布事件类型,优先级,黏性等)
//一旦EventBus#unregister被调用,active就会变成false,
//这将通过队列事件传递EventBus#invokeSubscriber来检查,以防止竞态条件。
volatile boolean active;
}
了解完订阅事件Subscription后,再阅读subscribe方法源码:首先是根据订阅方法,获取发布数据类型class,接着创建订阅事件,根据订阅事件集合是否为空,空则创建集合,并把发布数据class与订阅事件集合存入缓存;不为空则抛重复注册异常;接着根据订阅事件的优先级或是否到达末尾,把订阅事件插入适当的位置;然后根据发布数据class集合是否为空,空则创建,并把订阅者与发布事件集合存入缓存,不为空时,把发布的事件存入发布事件集合。最后根据是否为黏性事件完成事件注册。
下面看checkPostStickyEventToSubscription方法:
EventBus#checkPostStickyEventToSubscription
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {//stickyEvent必不为空
postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}
//根据订阅事件的线程模式执行不同的方法,第三个参数是判断是否为主线程
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING://在哪个线程post就在哪个线程接收事件并处理
invokeSubscriber(subscription, event);//反射调用method方法
break;
case MAIN://仅在主线程接收处理
if (isMainThread) {
invokeSubscriber(subscription, event);//反射调用method方法
} else {
mainThreadPoster.enqueue(subscription, event);//handler处理
}
break;
case BACKGROUND://仅在后台程接收处理
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);//线程池处理
} else {
invokeSubscriber(subscription, event);//反射调用method方法
}
break;
case ASYNC://另启线程(workthread)接收处理
asyncPoster.enqueue(subscription, event);//线程池处理
break;
default://不属于以上线程,直接抛未知线程异常
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
至此,EventBus的register方法分析完毕,下面看post方法:
EventBus#post
public void post(Object event) {
//获取发送线程的实例postingState
PostingThreadState postingState = currentPostingThreadState.get();
//获取派送事件队列,并把事件加入队列
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
if (!postingState.isPosting) {//事件未派送状态
//判断是否UI线程
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
postingState.isPosting = true;//事件派送状态标志位置为true
if (postingState.canceled) {//正在派送状态,如果被取消,抛内部异常
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) {
//当派送事件队列不为空时,对第一个事件进行派送,并移除该事件
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {//最终都会把是否在派送标志位和UI线程标志位置为false
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
//ThreadLocal可保证不同线程值多样性(线程独享),这里仅创建了一个PostingThreadState实例
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
//字面理解:发送线程的状态
//eventbus备注*For ThreadLocal, much faster to set (and get multiple values)*
final static class PostingThreadState {
final List<Object> eventQueue = new ArrayList<Object>();//事件队列
boolean isPosting;//标志位,是否在派送
boolean isMainThread;//标志位,是否主线程
Subscription subscription;//订阅事件处理器:订阅者+订阅方法+是否激活标志位
Object event;//事件
boolean canceled;//标志位,是否被取消
}
post方法很简单,大体思路:首先获取派送事件状态,然后把要派送的是按放入该派送事件状态的事件队列中,根据标志位未派送状态,对事件队列中的事件逐一取出并进行派送,并且最终把标志位是否被派送和UI线程置为false,下面看postSingleEvent方法是如何进行事件派送的:
EventBus#postSingleEvent
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;//默认订阅处理器未发现处理方法
//默认为true,表示订阅事件具有继承性,即该事件的父类或与该事件实现同一接口的订阅者都会处理该事件
if (eventInheritance) {
//查找所有可处理该事件相关类或接口
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {//遍历所有事件派送到的类
Class<?> clazz = eventTypes.get(h);
//检查这些可处理事件的类是否有处理对应事件的方法,返回值为boolean类型
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));
}
}
}
//查找所有事件类
private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
//private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
synchronized (eventTypesCache) {//同步锁
List<Class<?>> eventTypes = eventTypesCache.get(eventClass);
if (eventTypes == null) {
eventTypes = new ArrayList<>();
Class<?> clazz = eventClass;
//直到clazz为空跳出循环
while (clazz != null) {//查找派送事件的所有父类以及实现同一接口的类
eventTypes.add(clazz);
addInterfaces(eventTypes, clazz.getInterfaces());
clazz = clazz.getSuperclass();
}
//使用缓存把派送事件类型及其父类或实现同一接口类进行缓存
eventTypesCache.put(eventClass, eventTypes);
}
return eventTypes;
}
}
//检查所有可处理该派送事件的类
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {//根据相关List<?>取值subscriptions
subscriptions = subscriptionsByEventType.get(eventClass);
}
//如果订阅事件处理器不为空,且有值时,进行遍历,否则返回false
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) {//如果被取消,则跳出循环,返回false
break;
}
}
return true;
}
return false;
}
postSingleEvent方法首先根据发布的事件event来获取该发布事件的class,然后根据发布事件具有继承性,查找所有可消费处理该事件的相关类(订阅者)来处理该事件,过程中又回到前面已经分析过的postToSubscription方法,根据不同线程,调用不同方法对事件进行派发.至此,post方法也分析完毕.
EventBus#postSticky
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
补充说明下黏性事件,因为黏性事件其实也是调用post方法,只是在post之前先缓存了黏性事件而已.
最后分析一下反注册unregister方法
EventBus#unregister
public synchronized void unregister(Object subscriber) {
//private final Map<Object, List<Class<?>>> typesBySubscriber;
//从集合中取出该订阅者所有的订阅事件
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) {
//private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//从集合中取出所有关于该订阅者的订阅事件处理器
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;//标志位置为false
subscriptions.remove(i);//移除订阅事件处理器
i--;
size--;
}
}
}
}
反注册的逻辑也是很简单:首先根据订阅者从集合中取出该订阅者的所有订阅事件,然后在该订阅事件不为空时,进行遍历,并逐一进行解除.
OK,至此,EventBus源码分析完结!
T.T~