首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >100行代码拆解EventBus核心逻辑(二)

100行代码拆解EventBus核心逻辑(二)

作者头像
阳仔
发布于 2019-12-17 10:15:45
发布于 2019-12-17 10:15:45
43200
代码可运行
举报
文章被收录于专栏:终身开发者终身开发者
运行总次数:0
代码可运行

关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及AndroidPythonJava和Go,这个也是我们团队的主要技术栈。 Github:https://github.com/hylinux1024 微信公众号:终身开发者(angrycode)

问题

前面我们参考 EventBus 的实现逻辑模仿了一个最简单的 EasyBus。这个其实也是观察者模式的实现,所以整体逻辑理解起来应该是不难的。在 EasyBus 中进行注册的时候是通过反射机制对观察者的信息进行注册,然后解析出监听接口和事件类型( onEventXXXMethod(MessageEvent)方法以及其参数)。可以看出在这个注册的过程中,使用了运行时的反射机制,这在追求性能极致的基础组件中,这是可以优化的点。那么如何优化呢?这就需要用到今天提到的注解以及注解解析器的相关技术了。

注解

注解可以对包、类、接口方法、属性以及其它注解进行修饰,它是一个标记。就像所有的类继承于 Object一样,所有的注解本质都是继承于 Annotation这个接口。 如何定义注解呢? 这就需要使用元注解。元注解就是可以用来修饰其它注解的注解。 常见的元注解有

  • @Target 指定注解的作用目标。通过枚举 ElementType 来指定修饰包、类、方法、属性或者其它注解。
  • @Retention 指定注解的生命周期。同样通过枚举 RetentionPolicy 进行配置。生命周期从短到长为 RetentionPolicy.SOURCERetentionPolicy.CLASS, RetentionPolicy.RUNTIME 生命周期分别对应到源码文件、 Class文件以及运行时
  • @Documented 指定注解是否被包含在 JavaDoc
  • @Inherited 指定注解是否能被子类继承

例如常见的注解有 @Override@Deprecated@FuncationalInterface

看一下 @Override 的定义

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

该注解作用在方法中,并且生命周期是在编译期间就会被丢弃

再看一个 EventBus 中定义的注解

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
    ThreadMode threadMode() default ThreadMode.POSTING;

    /**
     * If true, delivers the most recent sticky event (posted with
     * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
     */
    boolean sticky() default false;

    /** Subscriber priority to influence the order of event delivery.
     * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
     * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
     * delivery among subscribers with different {@link ThreadMode}s! */
    int priority() default 0;
}

该注解作用于方法,且生命周期是最长的 Runtime 阶段,这个注解还定义了两个属性 stickypriority 分别表示这个事件是否是粘滞事件和事件的优先级。

注解解析器

EventBus 中默认是不使用注解解析器的,若要开启注解解析器生成索引辅助类,需要在 app/gradle 中配置 annotationProcessor

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
apply plugin: 'kotlin-kapt' // ensure kapt plugin is applied

dependencies {
    implementation 'org.greenrobot:eventbus:3.1.1'
    kapt 'org.greenrobot:eventbus-annotation-processor:3.1.1'
}

kapt {
    arguments {
        arg('eventBusIndex', 'com.github.easybus.MyEventBusIndex')
    }
}

由于我的 Demo 使用 Kotlin 编写,所以配置的是 kapt。详细配置文档可以参考EventBus文档

通过 AS 编译之后,就会在 build/generated/source/kapt/debug/com/github/easybus目录下生成索引文件 MyEventBusIndex 这个文件名称就是在 kapt 中配置的。

打开 MyEventBusIndex 源码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/** This class is generated by EventBus, do not edit. */
public class MyEventBusIndex implements SubscriberInfoIndex {
    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;

    static {
        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();

        putIndex(new SimpleSubscriberInfo(com.github.easybus.demo.MainActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onEventUpdate", com.github.easybus.demo.MessageEvent.class, ThreadMode.MAIN),
            new SubscriberMethodInfo("onEventUpdate2", com.github.easybus.demo.MessageEvent.class, ThreadMode.MAIN),
        }));

    }

    private static void putIndex(SubscriberInfo info) {
        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
    }

    @Override
    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
        if (info != null) {
            return info;
        } else {
            return null;
        }
    }
}

源码的逻辑很简单,内部是一个静态的 Map 类型的索引,存储了订阅者的信息,这个就是编译时动态生成的辅助类。在 static 代码块中,将订阅者 MainActivity 的信息 onEventUpdateonEventUpdate2 封装到 SubscriberInfo 中。 然后就可以在项目中使用这个索引辅助类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();

或者全局配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
// Now the default instance uses the given index. Use it like this:
EventBus eventBus = EventBus.getDefault();

通过它就可以避免在运行时对注解进行解析,使得基础组件的性能达到最佳。

总结

本文简单介绍了通过元注解自定义注解,以及在 EventBus 中是如何使用注解解析器提升性能。关于注解解析器的实现将在下一篇进行拆解。

引用
  • http://greenrobot.org/eventbus/documentation/subscriber-index/ EventBus 关于配置订阅者索引的官方文档
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 终身开发者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
100行代码拆解EventBus核心逻辑(三)
在前文的讲解中对 EventBus 的实现逻辑有了大概的理解之后,我们知道 Java 解析注解可以在运行时解析也可以在编译期间解析。由于运行时解析是通过反射来获取注解标记的类、方法、属性等对象,它的性能要受到反射的影响。因此在一些基础组件中更常见的做法是使用注解解析器技术,像 Dagger、 butterknife、 ARouter 以及本文所接触的 EventBus等框架库都是使用到了注解解析器的技术。接下来我们来实现一个注解解析器。(本文代码有点多)
阳仔
2019/12/17
5680
100行代码拆解EventBus核心逻辑(三)
老司机教你“飙”EventBus3
EventBus对于Android开发老司机来说肯定不会陌生,它是一个基于观察者模式的事件发布/订阅框架,开发者可以通过极少的代码去实现多个模块之间的通信,而不需要以层层传递接口的形式去单独构建通信桥梁。从而降低因多重回调导致的模块间强耦合,同时避免产生大量内部类。它拥有使用方便,性能高,接入成本低和支持多线程的优点,实乃模块解耦、代码重构必备良药。 作为Markus Junginger大神耗时4年打磨、超过1亿接入量、Github 9000+ star的明星级组件,分析EventBus的文章早已是数不
QQ音乐技术团队
2018/01/30
1.4K0
老司机教你“飙”EventBus3
EventBus源码解析
时近年末,但是也没闲着。最近正好在看 EventBus 的源码。那就正好今天来说说 EventBus 的那些事儿。
俞其荣
2022/07/28
5660
EventBus源码解析
Android面试之EventBus
众所周知,EventBus 是一款用在 Android 开发中的发布/订阅事件总线框架,基于观察者模式,将事件的接收者和发送者分开,简化了组件之间的通信操作,使用简单、效率高、体积小!
xiangzhihong
2022/11/30
6720
Greenrobot-EventBus源码学习(五)
EventBus 深入学习五之注册 订阅者的注册 + 消息推送 1. 注册 先贴出注册代码, 可以可到和 Guava 相比没什么大的区别, 主要的点在内部实现上,一个是如何获取注册信息;一个是如何保存注册关系 /** * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they * are no longer intere
一灰灰blog
2018/02/06
6780
EventBus3 学习笔记
脑图 概述 EventBus 是一款针对Android优化的发布/订阅(publish/subscribe)事件总线。主要功能是替代Intent,Handler,Broadcast在Fragment,
佛系编码
2018/05/22
6970
Android 框架学习2:源码分析 EventBus 3.0 如何实现事件总线
本文通过分析EventBus源码,从实现原理、设计思想、优缺点等方面进行介绍。EventBus主要利用了Java中的反射机制、观察者模式、工厂模式等,实现了高效、低延迟、线程安全的发布/订阅模式。同时,本文还介绍了EventBus在Android中的使用方式以及其与Otto等其他Android事件总线框架的区别。通过阅读本文,读者可以了解到EventBus的设计原理、实现方式以及其在Android开发中的应用,对于掌握Android事件总线框架的设计和实现具有一定的参考价值。
张拭心 shixinzhang
2018/01/05
1.6K0
Android 框架学习2:源码分析 EventBus 3.0 如何实现事件总线
Eventbus3代码分析(一):简单使用
之前一直是用的 eventbus2.4版本 eventbus很好用,因为实现解耦了,所以用起来很方便 但是,每次跟代码,查从哪里发出的,都需要从bean入手 比较麻烦 之前也见过有插件,可以帮助查找对应的源头,只是项目原因,没有使用 今天先简单记录一下使用
dodo_lihao
2018/09/12
4970
Eventbus3代码分析(一):简单使用
EventBus源码分析之订阅流程
订阅者可以是任何对象,唯一的要求是内部有@Subscribe修饰的方法,该方法是有一定要求的,这可以在后面的源码中看到EventBus对该方法的要求。
用户1108631
2019/08/17
7040
锦囊篇|一文摸懂EventBus
在app下的build.gradle的dependencies中进行引入,当然高版本也容易出现问题。
ClericYi
2020/06/23
4410
Greenrobot-EventBus源码学习(四)
EventBus 深入学习四之实例&类说明 本篇开始,则转向greenrobot/EventBus, 之前基本上将Guava中设计的思路捋了一遍,逻辑比较简单和清晰,接下来则看下广泛运用于android的这个框架又有什么不一样的地方,有什么独特的精妙所在 一些废话 开始之前,当然是要先把代码donw下来,然后本机能跑起来才行; so,基本的环境要搞起, Android Studio 将作为主要的ide 在导入工程之后,发现一直报一个 jdk版本过低的异常,解决方法是设置ide的jdk环境,如下,指定jd
一灰灰blog
2018/02/06
1.5K0
Greenrobot-EventBus源码学习(四)
EventBus源码解析
  相信大家已经非常熟练的使用EventBus了,简单的说EventBus是一个Android事件发布/订阅框架,通过解耦发布者和订阅者简化 Android 事件传递,是个典型的观察者模式,那么是什么是观察者模式,有个很形象的比喻:西游记中各路神仙一挥手,自己的坐骑就现出原形了,那么这些妖怪就是观察者,当他们观察到神仙挥手时就会现出原形。本文源码基于EventBus3.0。
黄林晴
2019/01/28
8910
EventBus初体验
本文主要给大家讲述下本人使用EventBus的经验和体会。EventBus是一款针对Android的发布/订阅事件总线的开源框架。它可以让我们很轻松地在Android各个组件之间传递消息,并且代码的可读性更好,耦合度更低。
open
2020/03/19
7520
EventBus初体验
Android EventBus3.0源码分析
在我们开发过程中,相信应该有很多人使用过EventBus 3.0,这个确实方便了我们,少些了很多代码,这是个优秀的库,我们接下来进行对他剖析。 我们使用EventBus 3.0的过程:
曾大稳
2018/09/11
4630
Eventbus3代码分析(四):@interface Subscribe分析
前面参考的代码,存放在(use_little_demo中的 eventbus3test) https://github.com/2954722256/use_little_demo
dodo_lihao
2018/09/12
5240
Eventbus3代码分析(四):@interface Subscribe分析
EventBus的基础学习
EventBus能够简化各组件间的通信,让我们的代码书写变得简单,在实际项目中也是会有用到,微服务间使用 eventbus实现系统间解耦,本小节来学习一下基础
在水一方
2022/09/07
2680
EventBus的基础学习
看看代码-EventBus
在需要注册的地方使用register方法注册,并给需要接受和处理消息的方法加上Subscribe注解。
NaOH
2018/06/13
5950
看看代码-EventBus
【EventBus】事件通信框架 ( 总结 | 手写事件通信框架完整代码示例 | 测试上述框架 )
该消息中心是事件通信框架的核心代码 , 负责订阅方法的注册 , 消息事件转发 , 订阅方法取消注册操作 ;
韩曙亮
2023/03/29
6400
【EventBus】事件通信框架 ( 总结 | 手写事件通信框架完整代码示例 | 测试上述框架 )
100行代码拆解EventBus核心逻辑(一)
EventBus 作为一个基础的消息传递组件,了解其核心实现原理是日常开发工作之外需要做的必修课。本系列希望通过自己实现一个类似的消息传递组件 EasyBus 来理解 EventBus 的核心实现原理。
阳仔
2019/11/23
4570
Android十八章:EventBus3.0使用
总之,他可以代替handler发送msg和Message接受msg,还可以代替intent在activity,fragment等传递msg。
ppjun
2018/09/05
5600
相关推荐
100行代码拆解EventBus核心逻辑(三)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档