前言

阅读本文之前,建议读者:

  • 对Arouter的使用有一定的了解。
  • 对Apt技术有所了解。

Arouter是一款Alibaba出品的优秀的路由框架,本文不对其进行全面的分析,只对其最重要的功能进行源码以及思路分析,至于其拦截器,降级,ioc等功能感兴趣的同学请自行阅读源码,强烈推荐阅读云栖社区的

这几个类都以Arouter$$Group开头,我们随便拿一个看看:

public class ARouter$$Group$$main implements IRouteGroup {   @Override   public void loadInto(Map<String, RouteMeta> atlas) {     atlas.put("/main/fa/leakscan", RouteMeta.build(RouteType.ACTIVITY, MainFaLeakScanActivity.class, "/main/fa/leakscan", "main", }}, -1, 1));     atlas.put("/main/login", RouteMeta.build(RouteType.ACTIVITY, LoginActivity.class, "/main/login", "main", null, -1, -2147483648));     atlas.put("/main/register", RouteMeta.build(RouteType.ACTIVITY, RegPhoneActivity.class, "/main/register", "main", null, -1, -2147483648));   } }

我们看到,他实现了loadInto方法,在这个方法中,它往这个HashMap中填充了好多数据,填充的是什么呢?填充的是路径path和它对应的目标RouteMeta,也就是我们最终需要的那层映射关系。而且,我们还能观察到:这个类下面所有的路由path都有一个共同点,即全是“/main”开头的,也就是说,这个类加载的映射关系,都是在一个组内的。因此我们总结出:

Arouter通过apt技术,为每个组生成了一个以Arouter$$Group开头的类,这个类负责向atlas这个Hashmap中填充组内路由数据。

IRouteGroup正如其名字,它就是一个能装载该组路由映射数据的类,其实有点像个工具类,为了方便后续讲解,我们姑且称上面这样一个实现了IRouteGroup的类叫做“组加载器”,本质是一个类。上图中的类是一个组加载器,其他所有以Arouter$$Group开头的类都是一个“组加载器”。回到之前的主线,Warehoust中的两个Hashmap,其中groupsIndex这个map中保存的是什么呢?我们通过它的调用找到这一行代码(已简化):

for (String className : routerMap) {      if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR +SUFFIX_ROOT)) {         ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);             } }

其中 ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR +SUFFIX_ROOT这行代码是几个静态字符串拼起来的,它等于 com.alibaba.android.arouter.routes.Arouter$$Root 。另外routerMap是什么呢?它是一个HashSet<String>:

routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);

这一行代码对它进行了初始化,目的是找到 com.alibaba.android.arouter.routes 这个包名下所有的类,将其类名保存到routerMap中。因此,上面的代码意思就是将com.alibaba.android.arouter.routes 包下所有名字以 com.alibaba.android.arouter.routes.Arouter$$Root 开头的类找出来,通过反射实例化并强转成IRouteRoot,然后调用loadInto方法。这里又出来一个新的接口:IRouteRoot,我们看代码:

public interface IRouteRoot {      /**      * Load routes to input      * @param routes input      */     void loadInto(Map<String, Class<? extends IRouteGroup>> routes); }

跟IRouteGroup长得还挺像,也是loadInto,我们看它的实现。还是以我的项目为例,在apt生成的文件夹下查找:
apt生成文件目录.png

最底下一行,有个Arouter$$Root$$app,它符合前面名字规则,我们进去看看: