文章目录

  • 一、EventBus 注册订阅者
  • 二、订阅方法
  • 三、查找订阅方法 findSubscriberMethods 方法
  • 四、查找订阅方法 findUsingInfo 方法
  • 五、查找订阅方法 findUsingReflectionInSingleClass

一、EventBus 注册订阅者


EventBus 中调用 EventBus.getDefault().register(this) 注册订阅者 ; 该方法中主要进行了如下 222 个步骤 :

  • ① 获取 订阅者 集合 , 查找当前订阅类中符合条件的订阅方法集合 ;
  • ② 遍历 订阅者 集合 , 进行事件订阅 , 保存数据 , 这些数据就是一些映射关系
/*** EventBus是Java和Android的中央发布/订阅事件系统。* 事件被发布({@link#post(Object)})到总线,总线将其传递给具有匹配处理程序的订阅者* 事件类型的方法。* 要接收事件,订阅者必须使用{@link#register(Object)}将自己注册到总线。* 一旦注册,订阅服务器将接收事件,直到调用{@link#unregister(Object)}。* 事件处理方法必须由{@link Subscribe}注释,必须是公共的,不返回任何内容(void),* 并且只有一个参数(事件)。*/
public class EventBus {/*** 注册给定订阅服务器以接收事件。订阅者一旦对接收事件不再感兴趣,就必须调用{@link#unregister(Object)}。* <p/>* 订阅服务器具有必须由{@link Subscribe}注释的事件处理方法。* {@link Subscribe}注释还允许类似{@link ThreadMode}和优先级的配置。*/public void register(Object subscriber) {Class<?> subscriberClass = subscriber.getClass();// 1. 获取 订阅者 集合 , 查找当前订阅类中符合条件的订阅方法集合 List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);// 2. 遍历 订阅者 集合 , 进行事件订阅 , 保存数据 , 这些数据就是一些映射关系 synchronized (this) {for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}}}
}

二、订阅方法


SubscriberMethod 对订阅的方法进行了一些封装 , 包括了方法的 Method 对象 Method method , 线程模式 ThreadMode threadMode , 事件类型 Class<?> eventType, 优先级 int priority , 粘性 boolean sticky 等 ;

/** 由EventBus内部使用并生成订户索引。 */
public class SubscriberMethod {final Method method;final ThreadMode threadMode;final Class<?> eventType;final int priority;final boolean sticky;/** Used for efficient comparison */String methodString;
}

三、查找订阅方法 findSubscriberMethods 方法


订阅方法缓存机制 : 从缓存中获取 订阅方法 , METHOD_CACHE 缓存是一个 HashMap 集合 ;

如果订阅者有很多方法 , 如果每次订阅都要查询所有的方法 , 如果遍历一次 Activity 的所有方法 很消耗性能 ; 因此这里引入了缓存机制 ;

第一次订阅时 , 将方法都放在缓存集合中 , 如果第二次订阅 , 不用再次查找方法 ;

如果缓存中没有订阅方法 , 那么说明这是第一次查找订阅方法 , 一般情况下都是调用 subscriberMethods = findUsingInfo(subscriberClass) 方法 , 获取订阅方法 ;

class SubscriberMethodFinder {// 方法缓存集合private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {// 从缓存中获取 订阅方法 , METHOD_CACHE 缓存是一个 HashMap 集合//     如果订阅者有很多方法 , 如果每次订阅都要查询所有的方法 , 很消耗性能 //     第一次订阅时 , 将方法都放在集合中 //       如果第二次订阅 , 不用再次查找方法List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);if (subscriberMethods != null) {return subscriberMethods;}// 如果缓存中没有订阅方法 , 那么说明这是第一次查找订阅方法// ignoreGeneratedIndex 属性默认是 false //     是否忽略注解生成器 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;}}
}

下面分析 findUsingInfo 方法 ;

四、查找订阅方法 findUsingInfo 方法


FindState 是辅助类 , 其中进行了状态保存等信息 ;

参数 Class<?> subscriberClass 是订阅者类 , 将订阅类设置到 FindState 查找状态类对象中 ;

该方法的核心是调用了 findUsingReflectionInSingleClass(findState) 方法 , 进行后续查找操作 ;

class SubscriberMethodFinder {private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {// FindState 是辅助类 , 其中进行了状态保存等信息 FindState findState = prepareFindState();// 将订阅类设置到 FindState 查找状态类对象中 findState.initForSubscriber(subscriberClass);// 订阅类的字节码类while (findState.clazz != null) {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);}
}

五、查找订阅方法 findUsingReflectionInSingleClass


通过反射获取订阅者类中的所有方法 , 遍历 订阅者 类中的所有方法 , 过滤掉不符合条件的方法 , 将符合条件的方法封装到 findState.subscriberMethods 集合中 ;

过滤方案 :

  • 订阅方法的参数个数肯定只有 1 个 ;
  • 订阅方法上有 @Subscribe 注解 ;
  • @Subscribe 注解属性判断 ;
  • @Subscribe 注解线程模式判断 ;
class SubscriberMethodFinder {private void findUsingReflectionInSingleClass(FindState findState) {Method[] methods;try {// 通过反射获取订阅者类中的所有方法 // 这比getMethods快,特别是当订阅者是像 Activity 这样的大类时methods = findState.clazz.getDeclaredMethods();} catch (Throwable th) {}// 遍历 订阅者 类中的所有方法 , 过滤掉不符合条件的方法 , for (Method method : methods) {int modifiers = method.getModifiers();if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {Class<?>[] parameterTypes = method.getParameterTypes();// 订阅方法的参数个数肯定只有 1 个if (parameterTypes.length == 1) {// 订阅方法上有 @Subscribe 注解 Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);if (subscribeAnnotation != null) {// @Subscribe 注解属性判断 Class<?> eventType = parameterTypes[0];if (findState.checkAdd(method, eventType)) {// @Subscribe 注解线程模式判断ThreadMode threadMode = subscribeAnnotation.threadMode();// 将符合条件的方法封装到 findState.subscriberMethods 集合中 ; findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky()));}}} } }}
}

【EventBus】EventBus 源码解析 ( 注册订阅者 | 订阅方法 | 查找订阅方法 )相关推荐

  1. 【EventBus】EventBus 源码解析 ( 注册订阅者 | 注册订阅方法详细过程 )

    文章目录 前言 一.EventBus 注册订阅者 二.注册订阅方法的具体过程 三.Subscription 类 前言 在上一篇博客 [EventBus]EventBus 源码解析 ( 注册订阅者 | ...

  2. 【EventBus】EventBus 源码解析 ( 注册订阅者总结 | EventBus 注册订阅者流程梳理 )

    文章目录 EventBus 注册订阅者流程梳理 EventBus 注册订阅者流程梳理 EventBus 注册订阅者流程梳理 : ① 在 客户端 调用 EventBus.getDefault().reg ...

  3. Android 源码分析之 EventBus 的源码解析

    1.EventBus 的使用 1.1 EventBus 简介 EventBus 是一款用于 Android 的事件发布-订阅总线,由 GreenRobot 开发,Gihub 地址是:EventBus. ...

  4. Android之EventBus框架源码解析上(单例模式)

    转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! 前言 EventBus能够简化各组件间的通信,让我们的代码书写变得简单,能有效的分 ...

  5. 【EventBus】EventBus 源码解析 ( 注册订阅者总结 | 从封装的数据结构角度分析 EventBus )

    文章目录 EventBus 中的重要数据类型 1.subscriptionsByEventType 集合 2.typesBySubscriber 集合 EventBus 中的重要数据类型 从几个关键的 ...

  6. 【EventBus】EventBus 源码解析 ( 事件发送 | 线程池中执行订阅方法 )

    文章目录 一.EventBus 中主线程支持类 二.EventBus 中 AsyncPoster 分析 三.AsyncPoster 线程池 Runnable 任务类 一.EventBus 中主线程支持 ...

  7. Android之EventBus框架源码解析下(源码解析)

    转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! 前言 EventBus是典型的发布订阅模式,多个订阅者可以订阅某个事件,发布者通过 ...

  8. Vue源码解析之Template转化为AST的实现方法

    什么是AST 在Vue的mount过程中,template会被编译成AST语法树,AST是指抽象语法树(abstract syntax tree或者缩写为AST),或者语法树(syntax tree) ...

  9. Kurento 源码解析系列(1)- PlayerEndpoint的play方法

    PlayerEndpoint.cpp 播放的流程解析 补充一个将源项目各个子项目整合并编译以后的工程地址 https://github.com/ywcai/JKms.git 针对如何编译源代码并在vs ...

最新文章

  1. window路径和linux路径变换,从linux样式路径转换时,Docker装入的卷将; C添加到Windows路径的末尾...
  2. 面试官:说说Spring AOP、AspectJ、CGLIB ?它们有什么关系?
  3. 马斯克雇机器狗勘察火箭爆炸现场,网友:《黑镜》现实版
  4. Scala _09样例类(case classes)隐式转换
  5. mysql多表内连接查询
  6. 论文浅尝 | S3QLRDF: 用于大规模RDF数据分布式SPARQL查询的关系分割架构
  7. 非关系型数据库--MongoDB
  8. 关于axios+spring boot无法进行重定向的问题
  9. linux移动文件夹覆盖,linux 批量文件移动及复制覆盖
  10. 代写COSC1295 Advanced Programming 作业、代做Java JDBC 程序设计作业、Java编程代写
  11. 黑马程序员 jQuery
  12. 10本Linux PDF 书籍免费分享
  13. 【基于stm32 FreeRtos的智能台灯控制】
  14. MS SQL数据库备份和恢复
  15. 基于LM的双目图像校准算法源码第一部分
  16. MongoDB查询之exists
  17. UE4 命令工具打包
  18. QT安装教程(简易)
  19. 矩阵连乘C语言递归实现
  20. runit 学习笔记

热门文章

  1. 查看字符集 oracle
  2. MIDlet 移动开发
  3. SPQuery 查询知多少
  4. 菜鸟玩基金(四)——注意事项
  5. Python笔记_第四篇_高阶编程_正则表达式_3.正则表达式深入
  6. SpringBoot 2.0 编程方式配置,不使用默认配置方式
  7. 对软件工程与计算机科学之间区别的看法
  8. 【转】Robot Framework 快速入门
  9. php+ tinymce粘贴word
  10. JSP+Servlet+Ajax实现用户增删改查的例子