上一篇文章水了一篇消息总线通信库EventBus的API使用,这一次来梳理一下它的源码,EventBus的源码不多,我们依旧按照API的使用方式来分析源代码会更好理解一点
为了方便起见,这里我把EventBus的注册传入对象类称之为订阅模块,把事件回调函数称之为消费函数
初始化
首先,EventBus的对象获取时通过EventBus.getDefault()来获取的,当看到这样的API调用的时候,我们自然而然的就能想到这是用的单例模式,让我们看看源码
//定义一个全局的静态变量defaultInstance,并使用volatile关键字修饰
//保证线程读取安全
static volatile EventBus defaultInstance;
/** Convenience singleton for apps using a process-wide EventBus instance. */
//使用多重同步校验获取EventBus对象
public static EventBus getDefault() {
EventBus instance = defaultInstance;
if (instance == null) {
synchronized (EventBus.class) {
instance = EventBus.defaultInstance;
if (instance == null) {
instance = EventBus.defaultInstance = new EventBus();
}
}
}
return instance;
}
getDefault()函数挺简单,就是静态变量defaultInstance不为空的情况下,直接返回EventBus对象,如果为空的情况下,则取new了一个EventBus对象,EventBus类一共有两个构造函数,分别是:
//公有构造
public EventBus()
//私有构造
EventBus(EventBusBuilder builder)
如果我们直接调用getDefault()函数,创建EventBus对象,则内部是调用公有构造,公有构造函数中,使用类中定义的静态私有常量DEFAULT_BUIDLER传给私有构造函数初始化EventBus,代码如下:
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
public EventBus() {
this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder) {
logger = builder.getLogger();
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
//粘性事件集
stickyEvents = new ConcurrentHashMap<>();
mainThreadSupport = builder.getMainThreadSupport();
//主UI线程消息提交器
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
//后台线程提交器
backgroundPoster = new BackgroundPoster(this);
//异步线程提交器
asyncPoster = new AsyncPoster(this);
//消费函数定义总数
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
//订阅模块管理
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
logSubscriberExceptions = builder.logSubscriberExceptions;
logNoSubscriberMessages = builder.logNoSubscriberMessages;
sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
//当事件触发时,如果方法调用异常,是否直接抛出异常,默认false
throwSubscriberException = builder.throwSubscriberException;
//继承事件,为true的情况下,当订阅者订阅事件的父类类型时,能
//得监听到该父类事件的所有子类事件, 默认true
eventInheritance = builder.eventInheritance;
//线程池
executorService = builder.executorService;
}
从上面基本上就可以看到,EventBus的初始化采用了构造者模式来初始化EventBus的工作环境,默认情况下采用DEFAULT_BUILDER构建信息,当然我们也可以自己来定制相关参数,那么久需要在调用getDefault()函数之前先来配置自己的参数,EventBus同样提供了一个builder()方法来获取EventBusBuidler对象
public static EventBusBuilder builder() {
return new EventBusBuilder();
}
然后EventBusBuilder中提供了如下函数来让我们定制工作环境
//配置为true后,消息分发过程中如果出现异常,将异常打印到logcat中
- logSubscriberExceptions(boolean logSubscriberExceptions)
//配置为true后,如果事件没有订阅模块,则打印LOG
- logNoSubscriberMessages(boolean logNoSubscriberMessages)
//配置为true后,如分发过程中出现异常情况,则将Exception作为异常事件分发
- sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent)
//分发没有订阅模块的事件
- sendNoSubscriberEvent(boolean sendNoSubscriberEvent)
//抛出分发过程中出现的异常
- throwSubscriberException(boolean throwSubscriberException)
//继承事件,模块监听事件的父类事件类型,则该事件的所有子类事件都能被该模块接收
- eventInheritance(boolean eventInheritance)
//线程池配置
- executorService(ExecutorService executorService)
//没有使用到
- skipMethodVerificationFor(Class<?> clazz)
//强制使用反射获取事件回调函数,即使其通过方法索引配置的。
- ignoreGeneratedIndex(boolean ignoreGeneratedIndex)
//消费函数严格校验,主要是事件回调函数如果不是public的,则抛出异常
- strictMethodVerification(boolean strictMethodVerification)
//添加消费函数回调索引
- addIndex(SubscriberInfoIndex index)
//日志器
- logger(Logger logger)
通过上述定制自己的EventBus工作环境之后,调用如下两个方法来初始化EventBus
//这是用来将参数赋予给默认的总线类,并创建EventBus对象
public EventBus installDefaultEventBus()
//这是根据当前配置创建一个新的EventBus对象
public EventBus build()
好了,源码分析到这里,我们大概应该对EventBus的实例构建有个粗略的了解了,原来我们在上一篇中,直接调用了getDefault()函数创建的EventBus只是使用了默认的构造器,那我们如果要定制默认Eventbus对象的运行环境,还可以在EventBus.getDefault()调用前做来配置:
EventBus.builder()
.eventInheritance(false)
.logNoSubscriberMessages(true)
.strictMethodVerification(true)
.sendSubscriberExceptionEvent(true)
.installDefaultEventBus()
好了,看了源码之后,还发现可以通过index的方式来注册事件回调方法
class RegisterSubscriber : SubscriberInfoIndex {
private val SUBSCRIBER_INDEX: HashMap<Class<*>, SubscriberInfo> = HashMap()
init {
val registerMethodInfo = arrayOf(
SubscriberMethodInfo("indexCallback", SubEvent::class.java, ThreadMode.MAIN),
SubscriberMethodInfo("indexCallback", SubEvent1::class.java, ThreadMode.BACKGROUND)
)
val registerMethodInfo1 = arrayOf(
SubscriberMethodInfo("callback", SubEvent::class.java, ThreadMode.MAIN)
)
SUBSCRIBER_INDEX[MainActivity::class.java] = SimpleSubscriberInfo(MainActivity::class.java, false, registerMethodInfo)
SUBSCRIBER_INDEX[DemoService::class.java] = SimpleSubscriberInfo(DemoService::class.java, false, registerMethodInfo1)
}
override fun getSubscriberInfo(subscriberClass: Class<*>): SubscriberInfo? {
return SUBSCRIBER_INDEX[subscriberClass]
}
}
EventBus.builder()
.eventInheritance(false)
.logNoSubscriberMessages(true)
.strictMethodVerification(true)
.sendSubscriberExceptionEvent(true)
.ignoreGeneratedIndex(false)
.addIndex(RegisterSubscriber())
.installDefaultEventBus()
class MainActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
EventBus.getDefault().register(this)
}
fun indexCallback(event:SubEvent){
Log.i("xx_debug","indexCallback SubEvent: $event")
}
fun indexCallback(event:SubEvent1){
Log.i("xx_debug","indexCallback SubEvent1: $event")
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
}
}
class DemoService : Service() {
override fun onCreate() {
super.onCreate()
EventBus.getDefault().register(this)
}
fun callback(e: SubEvent){
Log.i("xx_debug", "service callback: $e")
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
}
这样也可以,哈哈。 好了,这里大概把初始化的源码讲完了,比较简单,其实就是配置Builder构造器的参数。接下来看注册流程。
注册
事件监听模块通过 EventBus.getDefault().register(Object subscriber) 方法来完成,贴一下源码:
public void register(Object subscriber) {
//首先判断是否为Android平台,如果是Android平台,但是安卓组件不可用,则抛出异常
if (AndroidDependenciesDetector.isAndroidSDKAvailable() && !AndroidDependenciesDetector.areAndroidComponentsAvailable()) {
// Crash if the user (developer) has not imported the Android compatibility library.
throw new RuntimeException("It looks like you are using EventBus on Android, " +
"make sure to add the \"eventbus\" Android library to your dependencies.");
}
//通过传入的Object实例获取Class类
Class<?> subscriberClass = subscriber.getClass();
//根据订阅模块的Class类型,获取该模块的消费函数信息(一个订阅模块可以有多个消费函数,所以这里用List集合来存储消费函数信息)
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
//开始订阅
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
一步一步分析:
- AndroidDependenciesDetector.isAndroidSDKAvailable()
Android平台是否可用主要是通过反射framework.jar包中的Looper.java类,如果在运行环境能反射该类,
并且invoke getMainLooper()方法可以取得Looper对象且不为空,则表示当前运行在Android环境中。
- 查找模块中的消费函数信息
主要通过如下代码获取
List<SubscriberMethod> subscriberMethods =
subscriberMethodFinder.findSubscriberMethods(subscriberClass);
上面在初始化章节的时候看到过subscriberMethodFinder的赋值,
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
看到这个类的名称就知道它是干啥的了,所以编码的过程中,清晰的命名还是很重要的,这个类就是用来查找订阅模块中的消费函数的。它的构造函数如下
SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean
strictMethodVerification, boolean ignoreGeneratedIndex) {
this.subscriberInfoIndexes = subscriberInfoIndexes;
this.strictMethodVerification = strictMethodVerification;
this.ignoreGeneratedIndex = ignoreGeneratedIndex;
}
构造的几个参数都是从EventBuilder里面拿出来赋值给它的,几个参数的意义之前已经说过了,这个 SubscribeInfoIndexes的子集就是上面那个Demo中,通过函数索引的方式来定义消费函数监听事件的RegisterSubscriber这个类。继续往下走:
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//首先看缓存中有没有这个订阅模块信息,有的话直接返回,节省时间
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//没有缓存则继续找,如果不通过函数索引配置的方式,则通过注解从class信息中查找消费函数
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 {
//添加缓存,下次再用就不要找了,然后返回模块中的消费函数信息
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
先看ignoreGeneratedIndex = true的情况吧,也就是通过注解标记事件处理函数的方式。
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
//从对象池中获取FindState对象
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
//往上递归查找查找事件,遇到基类(以java,javax,android,androidx包名开头的类)则停止搜索
while (findState.clazz != null) {
//查找消费函数定义信息,并保存到findState中的subscriberMethods集合中
findUsingReflectionInSingleClass(findState);
//移到subscriberClass的父类Class继续扫描,直到遇到原生API定义的类则停止
findState.moveToSuperclass();
}
//返回消费函数信息
return getMethodsAndRelease(findState);
}
在分析里面的函数之前,需要先搞清楚一下这个FindState是什么东东,FindState类定义在SubscriberMethodFinder类中,是一个静态类,仅用于SubscriberMethodFinder内,工具人无疑。看看它的定义吧,内容还比较多
static class FindState {
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
//(event class : Method) 某个订阅模块中的事件类型对应的消费函数Method类
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
//(method key : Class) 消费函数签名与对应的订阅模块Class类的对应关系
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
//订阅模块的Class类
Class<?> subscriberClass;
Class<?> clazz;
boolean skipSuperClasses;
SubscriberInfo subscriberInfo;
//初始化订阅器信息
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
//释放资源
void recycle() {
subscriberMethods.clear();
anyMethodByEventType.clear();
subscriberClassByMethodKey.clear();
methodKeyBuilder.setLength(0);
subscriberClass = null;
clazz = null;
skipSuperClasses = false;
subscriberInfo = null;
}
boolean checkAdd(Method method, Class<?> eventType) {
// 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
// Usually a subscriber doesn't have methods listening to the same event type.
//检测当前事件类型是否有对应的消费函数,如果没有,则直接添加,然后返回成功
Object existing = anyMethodByEventType.put(eventType, method);
if (existing == null) {
return true;
} else {
//如果当前事件类型之前已经有与之对应的Method的了,则继续检查value对象是否为
//Method类型,为Method的情况下,通过函数签名去校验,
if (existing instanceof Method) {
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType);
}
}
//检查函数签名
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
//methodKey格式, exp: eventCallback>String
String methodKey = methodKeyBuilder.toString();
//获取定义该Method的Class类
Class<?> methodClass = method.getDeclaringClass();
//根据函数签名获取定义该函数的class类,如果子类未定义,则返回添加成功,
//如果子类中已经定义过并且已经缓存的methodClassOld是methodClass的子类,则校验成功
//否则返回失败。
Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
// Only add if not already found in a sub class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
//支持父类查找的情况下,调用此方法,则将需要遍历的Class类重置为clazz的父类
void moveToSuperclass() {
if (skipSuperClasses) {
clazz = null;
} else {
clazz = clazz.getSuperclass();
String clazzName = clazz.getName();
// Skip system classes, this degrades performance.
// Also we might avoid some ClassNotFoundException (see FAQ for background).
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") ||
clazzName.startsWith("android.") || clazzName.startsWith("androidx.")) {
clazz = null;
}
}
}
}
FindState分析完了,其实它就是一个在register过程中的工具类,用来缓存订阅模块中的消费函数相关信息,因为我们的订阅模块可能存在各种继承关系。对着findUsingReflection这个函数中的逻辑看就很清晰了,先以当前register传入的对象为基点向上遍历扫描所有父类中可能存在的消费函数,每个Class分析完成之后通过FindState的moveToSuperclass方法继续往上扫描,直到遇到java或者android的原生api类为止。所以当我们在使用EventBus过程中,如下定义都是可行的
open class RootClass{
@Subscribe
fun rootConsumer(value:String){
Log.i("xx_debug","root consume the $value")
}
}
open class ParentClass : RootClass(){
@Subscribe
fun parentConsumer(value:String){
Log.i("xx_debug","parent consume the $value")
}
}
class ChildClass : ParentClass(){
init {
EventBus.getDefault().register(this)
}
@Subscribe
fun eventConsumer(value:String){
Log.i("xx_debug","child consume the $value")
}
}
//触发时,上述中的所有Consumer都会被调用打印
EventBus.getDefault().post("111")
2022-08-03 17:12:01.792 8346-8346/com.test.kotlintest I/xx_debug: child consume the 111
2022-08-03 17:12:01.792 8346-8346/com.test.kotlintest I/xx_debug: parent consume the 111
2022-08-03 17:12:01.792 8346-8346/com.test.kotlintest I/xx_debug: root consume the 111
好了,最后还剩下一个查找消费函数的方法findUsingRelectionInSingleClass方法
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// This is faster than getMethods, especially when subscribers are fat classes like Activities
//查找订阅类中的所有定义的函数,结合上面的分析,我们知道了这个clazz是一直在变的,while
//循环一次clazz就赋值给了当前Class的父类Class,直到遇到原生API停止。
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
try {
methods = findState.clazz.getMethods();
} catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...
String msg = "Could not inspect methods of " + findState.clazz.getName();
if (ignoreGeneratedIndex) {
msg += ". Please consider using EventBus annotation processor to avoid reflection.";
} else {
msg += ". Please make this class visible to EventBus annotation processor to avoid reflection.";
}
throw new EventBusException(msg, error);
}
findState.skipSuperClasses = true;
}
//获取到Class中定义的所有方法后,通过注解标记,遍历出定义的消费函数
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注解修饰,如果存在,则为消费函数
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
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)) {
//如果消费函数不是public或者定义了其他的方法修饰符则报错
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
上述分析了在ignoreGeneratedIndex = true的情况下,查找消费函数信息的流程,那等于该值为false的情况呢,继续回到findSubscriberMethods函数中,走到了如下函数:
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//前面都是一样,这里则是从构造器中传入的函数索引信息中取订阅信息,函数索引的值以及在Finder中的赋值在初始化中已经介绍过了,这里直接拿到用。
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) {
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);
}
我们在初始化中的使用了函数索引的方式去定义消费函数,Demo中自定义的RegisterSubscriber类里面的函数都是字符串,那这里是怎么一个转换方式呢? 在findUsingInfo函数的子流程getSubscriberInfo函数中可以得到结果
private SubscriberInfo getSubscriberInfo(FindState findState) {
//findState.subscriberInfo.getSuperSubscriberInfo() 使用SimpleSubscriberInfo时为null
if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
}
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
//这里结合之前的Demo看,调用的是RegisterSubscriber中的getSubscriberInfo方法
//自己实现的,返回了类型为findState.clazz的SubscriberInfo
// return SUBSCRIBER_INDEX[subscriberClass]
//它的value是这种SimpleSubscriberInfo(MainActivity::class.java, false, registerMethodInfo)
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
紧接着又调用了SubscriberInfo的getSubscriberMethods方法
@Override
//定义在SimpleSubscriberInfo中
public synchronized SubscriberMethod[] getSubscriberMethods() {
int length = methodInfos.length;
SubscriberMethod[] methods = new SubscriberMethod[length];
for (int i = 0; i < length; i++) {
SubscriberMethodInfo info = methodInfos[i];
调用父类中的createSubscriberMethod方法构建了SubscriberMethodInfo对象
methods[i] = createSubscriberMethod(info.methodName, info.eventType, info.threadMode,
info.priority, info.sticky);
}
return methods;
}
createSubscriberMethod方法定义在抽象类AbstractSubscriberInfo中,可以根据函数名转成了Method对象
protected SubscriberMethod createSubscriberMethod(String methodName, Class<?> eventType, ThreadMode threadMode,
int priority, boolean sticky) {
try {
Method method = subscriberClass.getDeclaredMethod(methodName, eventType);
return new SubscriberMethod(method, eventType, threadMode, priority, sticky);
} catch (NoSuchMethodException e) {
throw new EventBusException("Could not find subscriber method in " + subscriberClass +
". Maybe a missing ProGuard rule?", e);
}
}
后面的流程基本就跟注册一样了,遍历父类,查找类中的定义的消费函数信息。这里还没完,这里才把消费函数的搜集走完,接下来继续回到register函数中,开始注册:
public void register(Object subscriber) {
...
...
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
subscribe函数比较简单,就是构建一个Subscription对象,然后将其加入到subscriptionsByEventType的HashMap中,如果是粘性事件则触发一次post
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
//构建Subscription对象
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//从本地缓存中查找当前事件的订阅模块集合,并将
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
//Subscription重写了equals,这里会对比subscriber是不是同一个对象,以及消费函数名称是否一致
//如果同一个订阅模块已经有相同事件类型的消费函数,则是重复订阅,报错。
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中
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//最后如果是粘性事件,则触发一次post动作
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的初始化通过构造者模式来完成,默认提供了一个构造器,也可以通过builder()的静态方法来自己构造EventBus运行环境,EventBus在注册时有两种方式去查找消费函数的Method对象,一个是通过@Subscribe注解,一个是通过在构造器中传入SubscriberInfoIndex实例来指定模块中的函数索引等信息,查找到消费函数信息之后,会构建一个Subscription的订阅器,EventBus中会通过事件类型分类保存这些订阅器对象,将订阅同一类型事件的订阅器保存在HashMap中,同时还会将每个订阅模块所订阅的事件类型保存在另外一个HashMap中,至于后面怎么用,下一篇再接着写吧。