【EventBus】EventBus 源码解析 ( 注册订阅者 | 订阅方法 | 查找订阅方法 )
文章目录
- 一、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 源码解析 ( 注册订阅者 | 订阅方法 | 查找订阅方法 )相关推荐
- 【EventBus】EventBus 源码解析 ( 注册订阅者 | 注册订阅方法详细过程 )
文章目录 前言 一.EventBus 注册订阅者 二.注册订阅方法的具体过程 三.Subscription 类 前言 在上一篇博客 [EventBus]EventBus 源码解析 ( 注册订阅者 | ...
- 【EventBus】EventBus 源码解析 ( 注册订阅者总结 | EventBus 注册订阅者流程梳理 )
文章目录 EventBus 注册订阅者流程梳理 EventBus 注册订阅者流程梳理 EventBus 注册订阅者流程梳理 : ① 在 客户端 调用 EventBus.getDefault().reg ...
- Android 源码分析之 EventBus 的源码解析
1.EventBus 的使用 1.1 EventBus 简介 EventBus 是一款用于 Android 的事件发布-订阅总线,由 GreenRobot 开发,Gihub 地址是:EventBus. ...
- Android之EventBus框架源码解析上(单例模式)
转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! 前言 EventBus能够简化各组件间的通信,让我们的代码书写变得简单,能有效的分 ...
- 【EventBus】EventBus 源码解析 ( 注册订阅者总结 | 从封装的数据结构角度分析 EventBus )
文章目录 EventBus 中的重要数据类型 1.subscriptionsByEventType 集合 2.typesBySubscriber 集合 EventBus 中的重要数据类型 从几个关键的 ...
- 【EventBus】EventBus 源码解析 ( 事件发送 | 线程池中执行订阅方法 )
文章目录 一.EventBus 中主线程支持类 二.EventBus 中 AsyncPoster 分析 三.AsyncPoster 线程池 Runnable 任务类 一.EventBus 中主线程支持 ...
- Android之EventBus框架源码解析下(源码解析)
转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! 前言 EventBus是典型的发布订阅模式,多个订阅者可以订阅某个事件,发布者通过 ...
- Vue源码解析之Template转化为AST的实现方法
什么是AST 在Vue的mount过程中,template会被编译成AST语法树,AST是指抽象语法树(abstract syntax tree或者缩写为AST),或者语法树(syntax tree) ...
- Kurento 源码解析系列(1)- PlayerEndpoint的play方法
PlayerEndpoint.cpp 播放的流程解析 补充一个将源项目各个子项目整合并编译以后的工程地址 https://github.com/ywcai/JKms.git 针对如何编译源代码并在vs ...
最新文章
- window路径和linux路径变换,从linux样式路径转换时,Docker装入的卷将; C添加到Windows路径的末尾...
- 面试官:说说Spring AOP、AspectJ、CGLIB ?它们有什么关系?
- 马斯克雇机器狗勘察火箭爆炸现场,网友:《黑镜》现实版
- Scala _09样例类(case classes)隐式转换
- mysql多表内连接查询
- 论文浅尝 | S3QLRDF: 用于大规模RDF数据分布式SPARQL查询的关系分割架构
- 非关系型数据库--MongoDB
- 关于axios+spring boot无法进行重定向的问题
- linux移动文件夹覆盖,linux 批量文件移动及复制覆盖
- 代写COSC1295 Advanced Programming 作业、代做Java JDBC 程序设计作业、Java编程代写
- 黑马程序员 jQuery
- 10本Linux PDF 书籍免费分享
- 【基于stm32 FreeRtos的智能台灯控制】
- MS SQL数据库备份和恢复
- 基于LM的双目图像校准算法源码第一部分
- MongoDB查询之exists
- UE4 命令工具打包
- QT安装教程(简易)
- 矩阵连乘C语言递归实现
- runit 学习笔记