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<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, 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。

作用:

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

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

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

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

延伸:

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • 小知识 观察者模式 :定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖它的对象都会得到通知并自...
    方言方言阅读 226评论 0 0
  • EventBus作用 事件总线用于观察者模式,用于通知使用,需要注册,和解注册,订阅要执行的方法,然后post发送...
    杨殿生阅读 1,375评论 0 0
  • EventBus是一个Android开源库,其使用发布/订阅模式,以提供代码间的松耦合。EventBus使用中央通...
    壮少Bryant阅读 650评论 0 4
  • 转自Android面试之EventBus原理分析[https://zhuanlan.zhihu.com/p/778...
    Miss_Ella阅读 239评论 0 2
  • 现实开发中用到的框架为了方便更好的理解加深记忆,归纳如下: 在开发中使用eventbus主要是为了进行传值和传...
    简书不简单iiii阅读 1,454评论 1 6