手写简化EventBus,理解框架核心原理

本文通过手写简化版的EventBus,解析框架的核心原理。介绍EventBus的发布-订阅者模式,实现包括注册、解注册、发送事件等关键功能,帮助读者深入理解EventBus的工作机制。
摘要由CSDN通过智能技术生成

前言

本来想学习下EventBus最新框架的源码,但是最新的框架的代码量已经很大了,很多都是锦上添花的东西,很多核心的原理代码需要从中剥离出来去了解。但是对于刚开始看源码就直接拿到这么功能丰富并完善的代码,可能收效甚微。为了自己学习并且帮助读者同志们学习,这里自己根据以前学习的经验理解,手写一份简化Eventbus源码,和大家一起学习此框架的要义。

EventBus技术架构

简介

Eventbus的存在是为了解决组件间的简单通信问题,采用发布-订阅者模式,通过统一的管理机构(bus总线)维护所有的订阅者,将发布者发布的消息发送对应订阅者的处理方法处理。
发布者和订阅者可以是任意Activity、Fragment、Service、Thread等,只要在一个进程中就可以,其不支持多进程。目前git地址为:https://github.com/greenrobot/EventBus。截至今日,最新版本3.2.0。
使用方法:

EventBus in 3 steps

   // 1.Define events: 定义Event,这里为用户使用时自定义的部分,框架不包含此格式,为任意java bean包含自己需要传输的信息。

    public static class MessageEvent {
    /* Additional fields if needed */ }


    //2 Prepare subscribers: Declare and annotate your subscribing method, optionally specify a thread mode:
    //准备订阅者方法,方法名是任意的,只是必须带@Subscribe注解,必须只有一个参数,参数需是第一步发送的消息。

    @Subscribe(threadMode = ThreadMode.MAIN)  
    public void onMessageEvent(MessageEvent event) {
   /* Do something */};

    //3.Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:
   // 注册和解注册eventbus,可以在activity和fragment、或者线程中,根据场景需要的时机进行注册解注册。

     @Override
     public void onStart() {
   
         super.onStart();
         EventBus.getDefault().register(this);
     }

     @Override
     public void onStop() {
   
         super.onStop();
         EventBus.getDefault().unregister(this);
     }

    //4.Post events: 发送event,可以是任何地方

     EventBus.getDefault().post(new MessageEvent());
架构原理

此架构图为EventBus原版的架构图。
在这里插入图片描述中间的EventBus是个大管家,负责所有消息流转和注册信息保存,程序运行起来时,注册者如Activity调用了register方法并把自己的this作为参数传入,大管家会登记所有的登记者和接收处理方法(@Subscribe注解方法)。当有发布者发布消息,即调用了EventBus.getDefault().post方法,将参数自定义Event发布到管家EventBus中, 大管家找到这个进程大家庭中所有注册了此Event类型的方法,并进行调用处理。

手写框架

模块

要手写框架,即需要包括框架核心原理和实现核心方法。这里进行列举,以明确程序框架。根据上节EventBus简介的使用方法可知需要实现:

  • 自定义注解@Subscribe和线程类型枚举。
  • EventBus类,并实现注册register方法、解注册方法unregister、post方法,且有getDefault单例方法。
  • 获取所有注册类中的加了@Subscribe注解的方法、方法参数和注解信息(线程和优先级信息)。
  • 实现post逻辑,即将发送Event到对应订阅方法参数是Event类型的方法
源码设计

菜谱有了,那就可以开始做菜了。如果想同时看着源码看文章的话,可以从github查看Demo。https://github.com/qingdaofu1/ZephyrBus
自定义注解和创建ThreadMode枚举类
自定义注解可以添加默认值,并且这里标注此注解是使用在方法上,并且是运行时保留策略,关于注解的详细原理可以参照我的另一篇总结:Android注解-看这篇文章就够了

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
   
    ThreadMode threadMode() default ThreadMode.POSTING;
    int priority() default 0;
}

线程模型肯定包括默认值POSTING,即和发送线程保持一致。MAIN线程即主线程,BACKGROUND即后台线程,非主线程。这里仅作示例,可以学习EventBus增加其他选项进行串行队列的处理或者线程池多线程等特性。

public enum ThreadMode {
   
    POSTING,
    MAIN,
    BACKGROUD
}

创建MyEventBus类和必要方法

  • 数据结构

为了保存订阅者的处理方法需要两个数据结构。
由于用户不一定在一个地方注册,即如果进程中Activity中、Fragment、Service等都有注册,则需要一个结合记录每个注册类中所有的订阅方法,这个集合即typesBySubscriber 。
然后比如用户有多种Event类型,比如Aevent、Bevent…,需要有个能记录所有处理Aevent的订阅者方法类和所有处理Bevent的方法类。如果有更多则记录更多。这个数据结构即subscriptionsByEventType ;其中的CopyOnWriteArrayList数据结构用法可以参考:CopyOnWriteArrayList的原理及使用
这里学习了源码中的数据结构名,以便读者返回读源码时更容易理解。

/**
     * 同一类型EventType类与所有注册方法的集合
     */
    private Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType = new HashMap<>();
    /**
     * 所有类有注册MyEventBus的  类与其内部所有处理方法集合。
     */
    private static final Map<Object, List
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值