EventBus原理总结

使用上比较简单,就是注册和解注册以及发送事件,外加一个黏性事件。

注册

注册主要是将当前Activity对象传进去,然后拿到对应的class;
反射拿到所有的方法,然后对方法进行过滤;需要有对应的注解,需要是public方法,需要是只有一个参数;
这中间入股需要追溯父类和接口,则需要去当前类的父类中去找对应的符合条件的方法,同时对参数的父类以及接口也有涉猎。
组装方法类,包括在什么线程执行,优先级等;
拿到当前类所有符合条件的组合方法后,执行订阅;
在订阅中,存在一个全局MAP,就是按照类型参数为key,当前类class和组合方法再组合的类组成的List作为value(一般接受事件会在多个Activity中都有涉猎),形成一个全局的大列表,保存起来。

如果在注册之前有黏性事件发送,则在注册后就立即执行之前的黏性事件。

发送事件

从大列表中,根据参数类型找到对应的再组合List,然后在指定的线程中反射执行。

黏性事件发送就是在发送事件的基础上增加一个List记录一下,这样在别的Activity中注册时会检测是否有需要执行的黏性事件,直接执行,执行完移除记录。List中存储的始终是未执行的。

解注册

没什么好说的,从对应的列表中移除。

索引

之前的操作都是在注册时反射操作,于性能上有损耗;索引是在编译期提前生成代码。需要增阿基注解处理器,注解处理器去生成,使用规则就是在初始化时增加索引;索引里面描述方法组合信息,这样就不用速反射查找了,提前自己查找好,然后添加进去,把反射的工作用手动替代了。

从性能上来说是提升了一点,但是从代码维护和编写上来说,累。

事件传递性

接收事件的class

  • 当前类中
    • 事件参数类型都会接收
    • 事件参数类型的父类也都会接收
  • 当前类父类中
    • 事件参数类型都会接收
    • 事件参数类型的父类也都会接收

还有一个不太靠谱的东西,就是当前类AA的父类A中,存在同名方法event,且方法参数类型都是发送类型;这种情况下,最多有一个,超过一个就报错。

当前类AA,父类A;
事件XX,父类X;
AA中的事件eventAA1(XX),eventAA2(XX);
A中的事件eventAA1(XX),eventAA2(XX);
发送事件post(XX)

上面父类A中有两个同名方法,就挂了,最多允许一个;XX换成X,也是如此。
真不靠谱,有啥意义呢?


2021-11-24补充

几个集合

private static final Map, List>> eventTypesCache = new HashMap<>();
private final Map, CopyOnWriteArrayList> subscriptionsByEventType;
private final Map>> typesBySubscriber;
private final Map, Object> stickyEvents;

一共四个集合;

第一个集合的用处和作用:

用处:
用于发射事件类型的继承性,如果要考虑继承性,会将事件类型的Class以及对应的父类Class,接口Class一直往上追溯,组装成一个Class列表作为value,然后以该事件类型的Class作为key。

作用:
在发射对应的事件时,如果考虑事件继承,则会把该事件对应的所有父类以及接口类Class都找出来,然后在另一个集合中(上面第二个集合)去查找已经注册过得“宿主”,然后执行。

第二个集合的用处和作用

用处:
“宿主”里面会有起码一个的注解事件方法,这里将注解事件方法拆分,拿到所有的信息(方法Method,执行线程,事件参数类型,优先级,黏性标签)组装成一个方法信息承载类SubscriberMethod,然后再组装一个“宿主-方法”信息承载类,里面包括“宿主”和SubscriberMethod,这个“宿主-方法”信息承载类就是Subscription;
一个事件类型可能会有多个“宿主”注册,这里以事件Class为key,Subscription组成的List为value。

作用:

在注册阶段收集,一是可以防止重复注册;而且在初测阶段就根据优先级排好了序;
再一个就是在时间发送时,根据事件Class找到所有注册过的方法,然后去反射执行。

延伸:

和第一个集合配合,就是第一个集合找到父类以及父接口等所有可追溯的Class,然后在这个集合中去查找对应搜集的方法。

第三个集合的作用和用处

用处:

以“宿主”为key,宿主里面的所有注册事件类型的Class组成的List为value。

作用:

在注册时搜集。
因为是以“宿主”为key的,所以可以对外提供方法,判断该宿主是否已经注册;

在解注册时,是要释放一个宿主,于是就根据当前“宿主”找到所有注册事件类型;找到了事件的类型,就到了第一个和第二个集合以事件类型为key的主场;第二个集合直接根据事件类型,找到对应的“宿主-方法”信息承载体,直接移除;

第一个集合啥都没做,为什么呢?因为没必要;首先解注册时释放的是“宿主”,而不是一个事件类型,所以该“宿主”里面注册的事件类型在别的地方可能也会用到;第二个就是这个事件类型对应的列表是一个缓存,下次进来或者别的页面也存在该事件类型的地方还会复用。所以释放意义不大。

另外他的作用是在发射事件的时候体现出来,他会遍历事件类型的父类以及接口等往上追溯的Class,对应的“宿主-方法”,然后去执行,但是查找需要第二个集合的帮忙,而第二个集合解注册时已经移除了,所以也不会有事件去响应。

第四个集合的作用和用处

用处:

用来手机黏性事件,事件参数Class为key,事件参数为value。

作用:

发射的时候搜集。
在“黏性宿主”注册时,去列表取出执行。

如果黏性事件类型有子类,则子类也会响应;但是这里不是自己去追溯子类,而是确实发射过子类的粘性事件并存储在该列表中。

上面那个子类做个解释,他不是直接去响应子类的方法;比如发射一个子类事件和父类事件,在”宿主“初始化注册时,如果注册了父类方法,则两个黏性事件都会在父类方法中标执行。
发送一个父类型,一个子类型,最终父事件中会执行父类型和子类型,子事件中只会执行子事件

所以黏性事件的这种机制还蛮奇怪的。

延伸:

并没有看到黏性事件的移除,也就意味着,这个黏性事件在执行后仍然会再次执行

你可能感兴趣的:(EventBus原理总结)