ARoute源码分析之初始化过程

2023-11-19

      已在多个项目中使用ARoute实现组件化间的路由通信,但是一直没有很完整的阅读过ARoute框架的源码。刚好这段时间想拜读一些知名框架的源码,那就从熟悉的ARoute开始吧!

若有错误的地方欢迎大家指正。


本篇博客就从ARoute的初始化流程开始,调用的初始化代码如下:

ARouter.init(getApplication());
ARouter.init(getApplication())方法实际调用的是_ARouter类里面的init(),ARoute中的代码如下:
    /**
     * Init, it must be call before used router.
     */
    public static void init(Application application) {
        if (!hasInit) {
            logger = _ARouter.logger;
            _ARouter.logger.info(Consts.TAG, "ARouter init start.");

            hasInit = _ARouter.init(application);

            、、、(暂时省略无关代码)
        }
    }

_ARoute中的init()代码如下:

    protected static synchronized boolean init(Application application) {
        mContext = application;
        LogisticsCenter.init(mContext, executor);
        logger.info(Consts.TAG, "ARouter init success!");
        hasInit = true;
        mHandler = new Handler(Looper.getMainLooper());

        return true;
    }

关键代码在于“LogisticsCenter.init(mContext, executor);”,下面就来分析这句代码里面都做了什么:

/**
 * LogisticsCenter init, load all metas in memory. Demand initialization
 */
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {

 ```
 try {
      ```
      Set<String> routerMap;
      // It will rebuild router map every times when debuggable.
      if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
          logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
          // These class was generated by arouter-compiler.
          routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
          if (!routerMap.isEmpty()) {
              context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE)
		       .edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply();
          }
          // Save new version name when router map update finishes.
          PackageUtils.updateVersion(context);    
      } else {
          logger.info(TAG, "Load router map from cache.");
          //Todo 遍历dex  根据包名获取所有的class文件,
          routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY,
	        Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
      }

      ```
      //todo  保存路由地址与类的对应关系
      for (String className : routerMap) {
        if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + 
            SUFFIX_ROOT)) {
            // This one of root elements, load root.
            ((IRouteRoot) (Class.forName(className).getConstructor().newInstance()))
		    .loadInto(Warehouse.groupsIndex);
        } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + 
                    SEPARATOR + SUFFIX_INTERCEPTORS)) {
            // Load interceptorMeta
            ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance()))
		    .loadInto(Warehouse.interceptorsIndex);
        } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + 
		            SEPARATOR + SUFFIX_PROVIDERS)) {
            // Load providerIndex    
            ((IProviderGroup) (Class.forName(className).getConstructor().newInstance()))
			.loadInto(Warehouse.providersIndex);
        }
      }
    }

     ```
 } catch (Exception e) {
     throw new HandlerException(TAG + "ARouter init logistics center exception!
                                [" + e.getMessage() + "]");
 }
}

上面代码隐藏了部分不重要的代码。

这段代码主要功能就是遍历dex文件,根据包名获取所有的类,然后判断类名中开头如果是:

“com.alibaba.android.arouter.routes.ARouter$$Root、 
com.alibaba.android.arouter.routes.ARouter$$Interceptors、  
com.alibaba.android.arouter.routes.ARouter$$Providers”

这三个类型,则构造出类并调用类中的loadInit()方法,那么接下来就看一下这三个类中的loadInit()具体做了什么:

/**
 * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. 
 */
public class ARouter$$Group$$arouter implements IRouteGroup {
  @Override
  public void loadInto(Map<String, RouteMeta> atlas) {
    atlas.put("/arouter/service/autowired", RouteMeta.build(RouteType.PROVIDER, 
              AutowiredServiceImpl.class, "/arouter/service/autowired", "arouter", null, 
              -1, -2147483648));
    atlas.put("/arouter/service/interceptor", RouteMeta.build(RouteType.PROVIDER,             
              InterceptorServiceImpl.class, "/arouter/service/interceptor", "arouter",     
              null, -1, -2147483648));
  }
}

三个类所在的位置如下图所示: 

        三个类都是相似的,接下来主要分析“ARouter$$Group/$/$arouter”。由其源码可知,这是ARoute自动生成的三个类,在loadInit()中的功能就是把各个URL对应的信息封装在RouteMeta对象中,然后存储到atlas,从上一步的源码可知这个传进来的atlas是Warehouse类中的静态Map类型变量,由此可知所有class与路由地址的映射关系都存储在这个Warehouse中。源码如下:

class Warehouse {
    // Cache route and metas
    static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
    static Map<String, RouteMeta> routes = new HashMap<>();

    // Cache provider
    static Map<Class, IProvider> providers = new HashMap<>();

    static Map<String, RouteMeta> providersIndex = new HashMap<>();

    // Cache interceptor
    static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new 
           UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]");
    static List<IInterceptor> interceptors = new ArrayList<>();

    static void clear() {
        routes.clear();
        groupsIndex.clear();
        providers.clear();
        providersIndex.clear();
        interceptors.clear();
        interceptorsIndex.clear();
    }
}

到此_ARouter.Init();就执行完了,再看回ARoute.init()方法中还做了什么:

 public static void init(Application application) {
        if (!hasInit) {
            ```
            hasInit = _ARouter.init(application);

            if (hasInit) {
                _ARouter.afterInit();
            }

            _ARouter.logger.info(Consts.TAG, "ARouter init over.");
        }
    }

从源码中可知,init完成后调用了_ARoute.afterInte()去创建了路由地址为“/arouter/service/interceptor”的拦截器,源码如下:

static void afterInit() {
    // Trigger interceptor init, use byName.
    interceptorService = (InterceptorService) 
       ARouter.getInstance().build("/arouter/service/interceptor").navigation();
    }

到此,ARoute的初始化流程源码分析暂时告一段落,下面贴上对应的时序图:

 分析完ARoute留下了两个疑问点:

1、ARoute是如何自动生成“ARouter/$/$Group$$xxx”这些文件的?

2、创建拦截器的代码其工作原理是什么:

(InterceptorService)ARouter.getInstance()
.build("/arouter/service/interceptor").navigation();

带着这两个问题,继续我们的ARoute源码阅读之旅......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ARoute源码分析之初始化过程 的相关文章

随机推荐

  • Qt使用https

    Qt貌似默认是不支持SSl认证的 可以这样操作 将 libeay32 dll和ssleay32 dll这两个库文件拷贝到程序生成目录下 即生成exe的同级目录 或者拷贝到QtNetwork模块的库文件目录中 路径示例 E Qt Qt5 12
  • qt orm 基于Qt的ORM框架QyOrm,类似peewee,最简单的语法,最高效的使用

    QyOrm Gitee传送门 支持功能 AutoGenerate根据数据库表自动生成类的定义代码 外键 实例化 联合查询 特殊查询 Json的读取和保存 QT GUI常见input widget 的双向绑定 以下是使用的例子 手动 类的定义
  • 第一篇:PyGame小游戏——2D迷宫游戏(16W字详解)

    目录 在开头的开场白 在CSDN看到一篇 利用深度优先算法自动生成随机迷宫 的blog 突发灵感 就想做这个迷宫游戏 本文大部分讲的意思 而非代码 文章最后会展示最终代码和图片的 读者不用过多地注意那些 本文是作者第一次写blog 难免有些
  • 【Java编程】关于Java的几个基础问题

    关于Java的几个基础问题 String 和 StringBuffer 和 StringBuilder 的异同 相同点 三者在 Java 中都是用来处理字符串的 三个类都被 final 修饰 因此都是不可继承的 StringBuilder
  • 超级等级福利礼包

    文章目录 一 介绍 二 设计等级礼包的目的 1 提升游戏玩家活跃度 2 提升游戏用户吸引力 3 提高游戏用户留存率 4 实现间接收入 5 持续营收 三 玩家心理总结 四 总结该模式的赢利点 五 该模式的应用场景举例 一 介绍 超级等级福利礼
  • 二分查找(C语言版)

    刚刚学到到的知识 掌握的不怎么好 如有不足麻烦留言 第一步 先理清你要查找的数组 最好是有序排序的数组 本人还没学到数组的排序就只能用有序的数组来 int arr 10 1 2 3 4 5 6 7 8 9 10 第二步 计算出该数组的长度
  • MATLAB(1)MATLAB工作环境

    目录 工具栏 当前文件夹窗口 命令行窗口 工作区 文件编辑窗口 图形 Figure x 窗口 本文基于MATLAB R2020b MATLAB刚打开时 一般如下图所示 包括上方的工具栏 左侧的当前文件夹窗口 中间的命令行窗口以及最右侧的工作
  • 考研机试题 -- 字符串、背包、枚举

    目录 首字母大写 字符串 日志排序 字符串 双关键字排序 字符串转换整数 字符串 点菜问题 01背包 神奇的口袋 01背包 计数 整数拆分 完全背包 计数 CCF201512 2 消除类游戏 枚举 首字母大写 字符串 https www n
  • 全球排名第一的免费开源ERP Odoo替代料管理应用解决方案

    本文节选自Odoo亚太金牌服务机构 开源智造 所编写的 ERP真的免费不花钱 Odoo应用指南 如需获取完整的知识内容 请至开源智造官网免费获取 感谢网友一键三连 点赞 转发 收藏 您的支持是我们最大的前进动力 电子行业产品竞争激烈 升级换
  • 【QT学习】实现MVC框架的简易封装(一文读懂)

    文章目录 前言 一 MVC框架简介 1 核心部件 2 使用目的 3 MVC优点 二 具体封装步骤 1 文件管理 2 创建模型 3 创建控制器 4 MVC实现 用户登录验证为例 总结 前言 MVC Model View Controller
  • Spring Boot中的JSON技术

    Spring Boot中的JSON技术 SpringBoot在处理对象的序列化和反序列的时候 底层用的是Jackson 来完成数据到实体类 实体类集合的映射 我们开发会指定 RequestBody ResponseBody 这样的注解 而了
  • java Map集合

    目录 一 介绍 二 HashMap 三 TreeMap 四 LinkedHashMap 一 介绍 Java中的Map是一种键值对的集合数据类型 用于存储无序的 不重复的键值对 它提供了快速的查找和访问功能 可以根据键来获取值 常见的Map实
  • ssh问题集锦

    Linux SSH连接提示 找不到匹配的host key算法 删除 etc ssh ssh host 修改 etc ssh sshd config KexAlgorithms diffie hellman group1 sha1 Ciphe
  • 如何撰写出色的软件专利技术交底书

    目录 目录 1 引言 2 技术交底书的基本要素 2 1 基础信息 2 2 缩略语和关键术语定义 2 3 发明名称 2 4 技术背景 2 5 技术方案 2 6 优点及效益 2 7 技术资料 附件 参考文献 3 准备工作 3 1 前期调研 3
  • OpenWRT初始化备份还原操作步骤

    初始化操作步骤 修改密码 ssh root 192 168 1 1 修改IP 添加网关 添加DNS vim etc config network 关闭dhcp vim etc config dhcp 修改时间 重启网络 service ne
  • 直流电机H桥的三种驱动方式:受限单机模式,单极模式,双极模式

    一 引出 1 简单的开关串联电机只能控制有刷直流电机的启停 要同时控制正反转和转速就要引入H桥式控制电路 2 对4个开关管的控制采用PWM 调节占空比可以实现调速 PWM频率一般在10KHz到20KHz之间 频率太低会导致电机转速过低 噪声
  • 对象作为数据成员

    02 Copyright c 2013 烟台大学计算机学院 04 作 者 马德鹏 05 完成日期 2014 年 4 月 4 日 06 版 本 号 v1 0 07 include
  • “鸿蒙”商标被抢先注册,华为上诉失败,鸿蒙系统将被迫改名?

    作为我国最著名的手机通讯企业之一 华为凭借着无与伦比的创新设计与可靠实用的用户体验 一度成为了国内最受欢迎的手机品牌 此外 华为手机在海外市场的销量也不遑多让 不仅质量优异 在通讯的稳定性与可靠性上 华为手机甚至胜过苹果 但是 因为众所周知
  • C++11中类数据成员初始化方法详解

    C 98为类中提供类成员的初始化列表 类对象的构造顺序是这样的 1 分配内存 调用构造函数时 隐式 显示的初始化各数据成员 2 进入构造函数后在构造函数中执行一般计算 1 类里面的任何成员变量在定义时是不能初始化的 2 一般的数据成员可以在
  • ARoute源码分析之初始化过程

    已在多个项目中使用ARoute实现组件化间的路由通信 但是一直没有很完整的阅读过ARoute框架的源码 刚好这段时间想拜读一些知名框架的源码 那就从熟悉的ARoute开始吧 若有错误的地方欢迎大家指正 本篇博客就从ARoute的初始化流程开