ARouter使用及原理分析
阅读原文时间:2021年04月21日阅读:2

简介

ARouter是阿里开源的路由组件,是 Android 平台中对页面、服务提供路由功能的中间件,常被用来进行组件化通讯。

功能介绍

  1. 支持直接解析标准URL进行跳转,并自动注入参数到目标页面中
  2. 支持多模块工程使用
  3. 支持添加多个拦截器,自定义拦截顺序
  4. 支持依赖注入,可单独作为依赖注入框架使用
  5. 支持InstantRun
  6. 支持MultiDex(Google方案)
  7. 映射关系按组分类、多级管理,按需初始化
  8. 支持用户指定全局降级与局部降级策略
  9. 页面、拦截器、服务等组件均自动注册到框架
  10. 支持多种方式配置转场动画
  11. 支持获取Fragment
  12. 完全支持Kotlin以及混编(配置见文末 其他#5)
  13. 支持第三方 App 加固(使用 arouter-register 实现自动注册)
  14. 支持生成路由文档
  15. 提供 IDE 插件便捷的关联路径和目标类

典型应用

  1. 从外部URL映射到内部页面,以及参数传递与解析
  2. 跨模块页面跳转,模块间解耦
  3. 拦截跳转过程,处理登陆、埋点等逻辑
  4. 跨模块API调用,通过控制反转来做组件解耦

基本使用

常用的使用方式,推荐直接参考官网文档,写的非常详细。
链接:https://github.com/alibaba/ARouter/blob/master/README_CN.md

源码分析

源码主要包含三个部分:

arouter-annotation:定义路由相关注解,Route(路由地址)、Autowired(属性装配)、Interceptor(路由拦截器)

arouter-compiler:注解处理器,用来生成路由表、属性装配器等java文件

arouter-api:路由api

大体思路是通过注解再编译期生成路由表,再ARouter.init()中将路由表加载到内存,然后调用api进行页面跳转等功能。

如果对自定义注解不了解的建议看下Java注解之编译时注解,另外arouter-compiler中使用JavaPoet Library来生成 Java 代码,JavaPoet 看这一篇就够了

arouter-annotation

arouter-annotation没什么说的,就是定义了路由需要的注解和数据结果

annotation

  • Route:路由定义注解,定义了path(路径)、group(分组,路由表是按组来继续管理的)、name(只在生成java文件的时候,添加注释用的)、priority(优先级)、extra(额外数据)等。主要是path和group其他的基本上没怎么用。
  • Autowired:属性自动装配注解,用于成员变量装配,比如Activity中经常使用getIntent().getExtra(),就可以通过Autowired注解来自定装配。
  • Interceptor:路由拦截器注解

enums

  • RouteType:路由类型,有用的就只有:ACTIVITY、PROVIDER、FRAGMENT另外SERVICE、BOARDCAST、CONTENT_PROVIDER有定义,但是没使用,并不能通过ARouter来发送广播或启动服务。
  • TypeKind:数据类型,用于成员变量自动装配

model

  • RouteMeta:路由的数据定义
  • TypeWrapper:获取class的type

arouter-compiler

定义了三个注解处理器:

  • RouteProcessor:处理Route注解,生成路由表
  • AutowiredProcessor:生成属性自动装配器
  • InterceptorProcessor:拦截器表,分不同优先级

RouteProcessor

/**
* 继承BaseProcessor,BaseProcessor中主要定义了类型、文件等工具类的引用、java版本进行初始化
**/
public class RouteProcessor extends BaseProcessor {
    //...省略代码
    //路由分组,前面也说了,路由是通过分组来进行管理的,每个路由分组对应一个java文件(ARouter$$Group$$组名),通过一个Root class(ARouter$$Root$$模块名称(Module))统一管理,ARouter.init时只会先加载Root,然后根据分组,在加载分组表。key:路由分组名称,value:路由表
    private Map<String, Set<RouteMeta>> groupMap = new HashMap<>(); // ModuleName and             routeMeta.
    //模块路由分组入口。key:分组名称,value:路由分组java文件路径
    private Map<String, String> rootMap = new TreeMap<>();  // Map of root metas, used for generate class file in order.
    // IProvider类型
    private TypeMirror iProvider = null;
    // java文件生成器
    private Writer docWriter;       // Writer used for write doc
    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        //...省略代码
        //初始化工具和类型
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (CollectionUtils.isNotEmpty(annotations)) {
            //获取Route注解
            Set<? extends Element> routeElements = roundEnv.getElementsAnnotatedWith(Route.class);
            try {
                logger.info(">>> Found routes, start... <<<");
                //处理Route注解,生成对应的路由java文件
                this.parseRoutes(routeElements);

            } catch (Exception e) {
                logger.error(e);
            }
            return true;
        }

        return false;
    } 
   //...省略代码
    private void parseRoutes(Set<? extends Element> routeElements) throws IOException {
        if (CollectionUtils.isNotEmpty(routeElements)) {
            //...省略代码
            //清空路由分组
            rootMap.clear();
            //获取activity类型
            TypeMirror type_Activity = elementUtils.getTypeElement(ACTIVITY).asType();
            //获取service类型
            TypeMirror type_Service = elementUtils.getTypeElement(SERVICE).asType();
            //获取fragment类型
            TypeMirror fragmentTm = elementUtils.getTypeElement(FRAGMENT).asType();
            //获取fragment V4类型 
            TypeMirror fragmentTmV4 = elementUtils.getTypeElement(Consts.FRAGMENT_V4).asType();

            //获取路由组接口
            TypeElement type_IRouteGroup = elementUtils.getTypeElement(IROUTE_GROUP);
            //获取iProvider组接口,提供通过class获取iProvider
            TypeElement type_IProviderGroup = elementUtils.getTypeElement(IPROVIDER_GROUP);
            ClassName routeMetaCn = ClassName.get(RouteMeta.class);
            ClassName routeTypeCn = ClassName.get(RouteType.class);

            /*
               定义方法参数类型:Map<String, Class<? extends IRouteGroup>>
             */
            ParameterizedTypeName inputMapTypeOfRoot = ParameterizedTypeName.get(
                    ClassName.get(Map.class),
                    ClassName.get(String.class),
                    ParameterizedTypeName.get(
                            ClassName.get(Class.class),
                            WildcardTypeName.subtypeOf(ClassName.get(type_IRouteGroup))
                    )
            );

            /*
             *定义方法参数类型:Map<String, RouteMeta>
             */
            ParameterizedTypeName inputMapTypeOfGroup = ParameterizedTypeName.get(
                    ClassName.get(Map.class),
                    ClassName.get(String.class),
                    ClassName.get(RouteMeta.class)
            );

            /*
             * 定义参数:(Map<String, Class<? extends IRouteGroup>> routes)
             */
            ParameterSpec rootParamSpec = ParameterSpec.builder(inputMapTypeOfRoot, "routes").build();
            /*
             *定义参数:(Map<String, RouteMeta> atlas)
             */
            ParameterSpec groupParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "atlas").build();
            /*
             *定义参数:(Map<String, RouteMeta> providers)
             */
            ParameterSpec providerParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "providers").build();  // Ps. its param type same as groupParamSpec!

            /*
             *创建加载路由分组的方法:
             *@Override
             *public void loadInto(Map<String, Class<? extends IRouteGroup>> routes)
             */
            MethodSpec.Builder loadIntoMethodOfRootBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
                    .addAnnotation(Override.class)
                    .addModifiers(PUBLIC)
                    .addParameter(rootParamSpec);

            //  Follow a sequence, find out metas of group first, generate java file, then statistics them as root.
            //遍历所以Route注解原始
            for (Element element : routeElements) {
                //获取元素类型
                TypeMirror tm = element.asType();
                //获取注解
                Route route = element.getAnnotation(Route.class);
                RouteMeta routeMeta;

                if (types.isSubtype(tm, type_Activity)) {                 
                    // Activity
                    // 存放所有被Autowired注解的成员变量<名称,类型>
                    Map<String, Integer> paramsType = new HashMap<>();
                    //<名称,注解>
                    Map<String, Autowired> injectConfig = new HashMap<>();
                    //变量Activity所有子节点
                    for (Element field : element.getEnclosedElements()) {
                        //如果是成员变量并且不是iProvider的子类
                        if (field.getKind().isField() && field.getAnnotation(Autowired.class) != null && !types.isSubtype(field.asType(), iProvider)) {
                            // It must be field, then it has annotation, but it not be provider.                    
                            Autowired paramConfig = field.getAnnotation(Autowired.class);
                            //注入名称,如果Autowired注解不带name,就以变量名做name
                            String injectName = StringUtils.isEmpty(paramConfig.name()) ? field.getSimpleName().toString() : paramConfig.name();
                            //添加名称、类型,paramsType和injectConfig主要用来生成文档和Uri参数解析,并不用于变量注入,activity成员变量的注入,主要还是靠AutowiredProcessor生产的注入器来实现。
                            paramsType.put(injectName, typeUtils.typeExchange(field));
                            injectConfig.put(injectName, paramConfig);
                        }
                    }
                    //创建RouteMeta
                    routeMeta = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType);
                    routeMeta.setInjectConfig(injectConfig);
                } else if (types.isSubtype(tm, iProvider)) {         
                    // IProvider
                    logger.info(">>> Found provider route: " + tm.toString() + " <<<");
                    routeMeta = new RouteMeta(route, element, RouteType.PROVIDER, null);
                } else if (types.isSubtype(tm, type_Service)) {           
                    // Service,这个基本上没用,ARouter目前并不支持启动服务
                    routeMeta = new RouteMeta(route, element, RouteType.parse(SERVICE), null);
                } else if (types.isSubtype(tm, fragmentTm) || types.isSubtype(tm, fragmentTmV4)) {
                    //fragment
                    logger.info(">>> Found fragment route: " + tm.toString() + " <<<");
                    routeMeta = new RouteMeta(route, element, RouteType.parse(FRAGMENT), null);
                } else {
                    throw new RuntimeException("ARouter::Compiler >>> Found unsupported class type, type = [" + types.toString() + "].");
                }
                //添加分组
                categories(routeMeta);
            }
            /*
             *创建加载iProvider表的方法:
             *@override 
             *public void loadInto((Map<String, RouteMeta> providers))
             *
             */
            MethodSpec.Builder loadIntoMethodOfProviderBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
                    .addAnnotation(Override.class)
                    .addModifiers(PUBLIC)
                    .addParameter(providerParamSpec);

            Map<String, List<RouteDoc>> docSource = new HashMap<>();

            // Start generate java source, structure is divided into upper and lower levels, used for demand initialization.
            //变量所有路由分组
            for (Map.Entry<String, Set<RouteMeta>> entry : groupMap.entrySet()) {
                //获取路由分组名称
                String groupName = entry.getKey();
                /*
                 *创建加载路由列表方法:
                 *@Override
                 *public void loadInfo(Map<String, RouteMeta> atlas)
                 */
                MethodSpec.Builder loadIntoMethodOfGroupBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
                        .addAnnotation(Override.class)
                        .addModifiers(PUBLIC)
                        .addParameter(groupParamSpec);

                List<RouteDoc> routeDocList = new ArrayList<>();

                // Build group method body
                Set<RouteMeta> groupData = entry.getValue();
                //遍历当前分组的所有节点
                for (RouteMeta routeMeta : groupData) {
                    RouteDoc routeDoc = extractDocInfo(routeMeta);

                    ClassName className = ClassName.get((TypeElement) routeMeta.getRawType());
                    //根据不同的类型在不同的loadInfo方法中,添加语句,将当前节点加入对应的表中
                    switch (routeMeta.getType()) {
                        //当前节点是iProvider,在public void loadInto((Map<String, RouteMeta> providers))方法中加入providers.put(class,routeMeta)
                        case PROVIDER:  
                            //获取所有继承的接口
                            List<? extends TypeMirror> interfaces = ((TypeElement) routeMeta.getRawType()).getInterfaces();
                            for (TypeMirror tm : interfaces) {
                                routeDoc.addPrototype(tm.toString());
                                //如果直接继承iProvider,providers.put("com.alibaba.android.arouter.facade.template.IProvider",routeMeta)
                                if (types.isSameType(tm, iProvider)) {   
                                    loadIntoMethodOfProviderBuilder.addStatement(
                                            "providers.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, null, " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))",
                                            (routeMeta.getRawType()).toString(),
                                            routeMetaCn,
                                            routeTypeCn,
                                            className,
                                            routeMeta.getPath(),
                                            routeMeta.getGroup());
                                } else if (types.isSubtype(tm, iProvider)) {
                                //如果是iProvider的子类,providers.put(当前类型的全路径,routeMeta)
                                    loadIntoMethodOfProviderBuilder.addStatement(
                                            "providers.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, null, " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))",
                                            tm.toString(),    // So stupid, will duplicate only save class name.
                                            routeMetaCn,
                                            routeTypeCn,
                                            className,
                                            routeMeta.getPath(),
                                            routeMeta.getGroup());
                                }
                            }
                            break;
                        default:
                            break;
                    }

                    // 其他类型
                    StringBuilder mapBodyBuilder = new StringBuilder();
                    //后面这部分主要用于生成文档,不影响路由表的生成
                    Map<String, Integer> paramsType = routeMeta.getParamsType();
                    Map<String, Autowired> injectConfigs = routeMeta.getInjectConfig();
                    if (MapUtils.isNotEmpty(paramsType)) {
                        List<RouteDoc.Param> paramList = new ArrayList<>();

                        for (Map.Entry<String, Integer> types : paramsType.entrySet()) {
                            mapBodyBuilder.append("put(\"").append(types.getKey()).append("\", ").append(types.getValue()).append("); ");

                            RouteDoc.Param param = new RouteDoc.Param();
                            Autowired injectConfig = injectConfigs.get(types.getKey());
                            param.setKey(types.getKey());
                            param.setType(TypeKind.values()[types.getValue()].name().toLowerCase());
                            param.setDescription(injectConfig.desc());
                            param.setRequired(injectConfig.required());

                            paramList.add(param);
                        }

                        routeDoc.setParams(paramList);
                    }
                    String mapBody = mapBodyBuilder.toString();
                    /*
                     *路由表加载方法
                     * public void loadInfo(Map<String, RouteMeta> atlas)中添加语句
                     * atlas.put(路由路径,routeMeta)
                     */
                    loadIntoMethodOfGroupBuilder.addStatement(
                            "atlas.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, " + (StringUtils.isEmpty(mapBody) ? null : ("new java.util.HashMap<String, Integer>(){{" + mapBodyBuilder.toString() + "}}")) + ", " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))",
                            routeMeta.getPath(),
                            routeMetaCn,
                            routeTypeCn,
                            className,
                            routeMeta.getPath().toLowerCase(),
                            routeMeta.getGroup().toLowerCase());

                    routeDoc.setClassName(className.toString());
                    routeDocList.add(routeDoc);
                }

                /* 生成路由组java文件:
                public class ARouter$$Group&&组名 implements IRouteGroup{
                    @Override
                    void loadInto(Map<String, RouteMeta> atlas){
                        atlas.put(路由名,RouteMeta);
                        ...
                    }
                }
                */
                String groupFileName = NAME_OF_GROUP + groupName;
                JavaFile.builder(PACKAGE_OF_GENERATE_FILE,
                        TypeSpec.classBuilder(groupFileName)
                                .addJavadoc(WARNING_TIPS)
                                .addSuperinterface(ClassName.get(type_IRouteGroup))
                                .addModifiers(PUBLIC)
                                .addMethod(loadIntoMethodOfGroupBuilder.build())
                                .build()
                ).build().writeTo(mFiler);

                logger.info(">>> Generated group: " + groupName + "<<<");
                //将路由分组java文件路径添加到rootMap
                rootMap.put(groupName, groupFileName);
                docSource.put(groupName, routeDocList);
            }

            if (MapUtils.isNotEmpty(rootMap)) {
                // Generate root meta by group name, it must be generated before root, then I can find out the class of group.
                for (Map.Entry<String, String> entry : rootMap.entrySet()) {
                    /*
                      加载路由分组的方法添加语句
                      public void loadInto(Map<String, Class<? extends IRouteGroup>> routes){
                            routes.put(分组名,路由分组java文件路径)
                      }
                    */
                    loadIntoMethodOfRootBuilder.addStatement("routes.put($S, $T.class)", entry.getKey(), ClassName.get(PACKAGE_OF_GENERATE_FILE, entry.getValue()));
                }
            }

            // Output route doc
            if (generateDoc) {
                docWriter.append(JSON.toJSONString(docSource, SerializerFeature.PrettyFormat));
                docWriter.flush();
                docWriter.close();
            }

            // Write provider into disk
            /*
             创建IPovider路由表类java文件
             public class ARouter$$Providers$$模块名称 implements IProviderGroup{
                @Override
                public void loadInto(Map<String, RouteMeta> providers){
                    providers.put(IPovider或子类全路径,RouteMeta);
                    ...
                }
             }

            */
            String providerMapFileName = NAME_OF_PROVIDER + SEPARATOR + moduleName;
            JavaFile.builder(PACKAGE_OF_GENERATE_FILE,
                    TypeSpec.classBuilder(providerMapFileName)
                            .addJavadoc(WARNING_TIPS)
                            .addSuperinterface(ClassName.get(type_IProviderGroup))
                            .addModifiers(PUBLIC)
                            .addMethod(loadIntoMethodOfProviderBuilder.build())
                            .build()
            ).build().writeTo(mFiler);

            logger.info(">>> Generated provider map, name is " + providerMapFileName + " <<<");

            // Write root meta into disk.
            /*
             创建路由分组管理类
              public class ARouter$$Root$$模块名 implements IRouteRoot{
                @Override
                public void loadInto(Map<String, Class<? extends IRouteGroup>> routes){
                    routes.put(组名,路由分组类class);
                    ...
                }
              }
            */
            String rootFileName = NAME_OF_ROOT + SEPARATOR + moduleName;
            JavaFile.builder(PACKAGE_OF_GENERATE_FILE,
                    TypeSpec.classBuilder(rootFileName)
                            .addJavadoc(WARNING_TIPS)
                            .addSuperinterface(ClassName.get(elementUtils.getTypeElement(ITROUTE_ROOT)))
                            .addModifiers(PUBLIC)
                            .addMethod(loadIntoMethodOfRootBuilder.build())
                            .build()
            ).build().writeTo(mFiler);

            logger.info(">>> Generated root, name is " + rootFileName + " <<<");
        }
    }
    /**
     * 添加routeMete到对应分组
     *
     * @param routeMete metas.
     */
    private void categories(RouteMeta routeMete) {
        //校验routeMete分组信息,如果没有组名,以第一个"/"与第二个"/"之间的名字作为组名,如果都不存在则无效
        if (routeVerify(routeMete)) {
            //根据组名获取分组
            Set<RouteMeta> routeMetas = groupMap.get(routeMete.getGroup());
            //如果分组不存在
            if (CollectionUtils.isEmpty(routeMetas)) {
                //创建一个分组
                Set<RouteMeta> routeMetaSet = new TreeSet<>(new Comparator<RouteMeta>() {
                    @Override
                    public int compare(RouteMeta r1, RouteMeta r2) {
                        try {
                            return r1.getPath().compareTo(r2.getPath());
                        } catch (NullPointerException npe) {
                            logger.error(npe.getMessage());
                            return 0;
                        }
                    }
                });
                routeMetaSet.add(routeMete);
                groupMap.put(routeMete.getGroup(), routeMetaSet);
            } else {
                //已经存在分组,直接添加
                routeMetas.add(routeMete);
            }
        } else {
            logger.warning(">>> Route meta verify error, group is " + routeMete.getGroup() + " <<<");
        }
    }
}

RouteProcessor主要生成了三个java文件:路径在对应模块的build/generated/ap_generated_sources/debug/out/com.alibaba.android.arouter.routes下

public class ARouter$$Group&&组名 implements IRouteGroup{
    @Override
    public void loadInto(Map<String, RouteMeta> atlas){
        atlas.put(路由名,RouteMeta);
        ...
    }
}

public class ARouter$$Providers$$模块名称 implements IProviderGroup{
    @Override
    public void loadInto(Map<String, RouteMeta> providers){
        providers.put(IPovider或子类全路径,RouteMeta);
        ...
    }
}

public class ARouter$$Root$$模块名 implements IRouteRoot{
    @Override
        public void loadInto(Map<String, Class<? extends IRouteGroup>> routes){
            routes.put(组名,路由分组类class);
            ...
    }
}

例如:

public class ARouter$$Root$$app implements IRouteRoot {
  @Override
  public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
    routes.put("baseUrl", ARouter$$Group$$baseUrl.class);
    routes.put("guide", ARouter$$Group$$guide.class);
    routes.put("main", ARouter$$Group$$main.class);
    routes.put("noteDb", ARouter$$Group$$noteDb.class);
    routes.put("share", ARouter$$Group$$share.class);
    routes.put("translateDb", ARouter$$Group$$translateDb.class);
    routes.put("vip", ARouter$$Group$$vip.class);
  }
}
public class ARouter$$Providers$$app implements IProviderGroup {
  @Override
  public void loadInto(Map<String, RouteMeta> providers) {
    providers.put("com.iflytek.tibet.core.http.IBaseUrlProvider", RouteMeta.build(RouteType.PROVIDER, TibetUrlProvider.class, "/baseUrl/provider", "baseUrl", null, -1, -2147483648));
    providers.put("com.iflytek.tibet.translate.db.provider.ITranslateDbProvider", RouteMeta.build(RouteType.PROVIDER, TibetTranslateDbProvider.class, "/translateDb/provider", "translateDb", null, -1, -2147483648));
    providers.put("com.iflytek.tibet.note.db.INoteDbProvider", RouteMeta.build(RouteType.PROVIDER, TibetNoteDbProvider.class, "/noteDb/provider", "noteDb", null, -1, -2147483648));
    providers.put("com.iflytek.tibet.core.share.IShareProvider", RouteMeta.build(RouteType.PROVIDER, TibetShareProvider.class, "/share/provider", "share", null, -1, -2147483648));
  }
}
public class ARouter$$Group$$main implements IRouteGroup {
  @Override
  public void loadInto(Map<String, RouteMeta> atlas) {
    atlas.put("/main/agreement", RouteMeta.build(RouteType.ACTIVITY, UserAgreementActivity.class, "/main/agreement", "main", null, -1, -2147483648));
  }
}

InterceptorProcessor

public class InterceptorProcessor extends BaseProcessor {
    /**
     * 拦截器列表,<优先级,拦截器节点>,优先级从0开始,依次递减
     */
    private Map<Integer, Element> interceptors = new TreeMap<>();
    //...省略代码
    /**
     * {@inheritDoc}
     *
     * @param annotations
     * @param roundEnv
     */
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (CollectionUtils.isNotEmpty(annotations)) {
            //获取说有Interceptor注解
            Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Interceptor.class);
            try {
                //处理注解
                parseInterceptors(elements);
            } catch (Exception e) {
                logger.error(e);
            }
            return true;
        }

        return false;
    }

    /**
     * Parse tollgate.
     *
     * @param elements elements of tollgate.
     */
    private void parseInterceptors(Set<? extends Element> elements) throws IOException {
        if (CollectionUtils.isNotEmpty(elements)) {
            //便利Interceptor注解原始
            for (Element element : elements) {
                //校验原始
                if (verify(element)) {
                    //获取Interceptor注解
                    Interceptor interceptor = element.getAnnotation(Interceptor.class);
                    //检查是否已经存在相同优先级的拦截器,有就抛出异常
                    Element lastInterceptor = interceptors.get(interceptor.priority());
                    if (null != lastInterceptor) {
                        throw new IllegalArgumentException(
                                String.format(Locale.getDefault(), "More than one interceptors use same priority [%d], They are [%s] and [%s].",
                                        interceptor.priority(),
                                        lastInterceptor.getSimpleName(),
                                        element.getSimpleName())
                        );
                    }
                    //不存在相同优先级的拦截器,加入列表
                    interceptors.put(interceptor.priority(), element);
                } else {
                    logger.error("A interceptor verify failed, its " + element.asType());
                }
            }

            //获取IInterceptor接口
            TypeElement type_ITollgate = elementUtils.getTypeElement(IINTERCEPTOR);
            //获取IInterceptorGroup接口
            TypeElement type_ITollgateGroup = elementUtils.getTypeElement(IINTERCEPTOR_GROUP);
            /**
             *创建参数类型Map<Integer, Class<? extends IInterceptor>>
             **/
            ParameterizedTypeName inputMapTypeOfTollgate = ParameterizedTypeName.get(
                    ClassName.get(Map.class),
                    ClassName.get(Integer.class),
                    ParameterizedTypeName.get(
                            ClassName.get(Class.class),
                            WildcardTypeName.subtypeOf(ClassName.get(type_ITollgate))
                    )
            );

            //创建参数Map<Integer, Class<? extends IInterceptor>> interceptors
            ParameterSpec tollgateParamSpec = ParameterSpec.builder(inputMapTypeOfTollgate, "interceptors").build();

            /**
             * 创建方法
             * @Override
             * public void loadInfo(Map<Integer, Class<? extends IInterceptor>> interceptor)
             *
             */
            MethodSpec.Builder loadIntoMethodOfTollgateBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
                    .addAnnotation(Override.class)
                    .addModifiers(PUBLIC)
                    .addParameter(tollgateParamSpec);

            /**
             * 添加将各个拦截器加入列表的语句
             * @Override
             * public void loadInfo(Map<Integer, Class<? extends IInterceptor>> interceptor){
             *     interceptors.put(优先级,拦截器类信息)
             * }
             */
            if (null != interceptors && interceptors.size() > 0) {
                // Build method body
                for (Map.Entry<Integer, Element> entry : interceptors.entrySet()) {
                    loadIntoMethodOfTollgateBuilder.addStatement("interceptors.put(" + entry.getKey() + ", $T.class)", ClassName.get((TypeElement) entry.getValue()));
                }
            }

            /**
             * 创建添加Interceptor列表类
             * public class ARouter$$Interceptors$$模块名称 implements IInterceptorGroup{
             *     @Override
             *     public void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptor){
             *         interceptors.put(优先级,拦截器类信息);
             *     }
             * }
             */
            JavaFile.builder(PACKAGE_OF_GENERATE_FILE,
                    TypeSpec.classBuilder(NAME_OF_INTERCEPTOR + SEPARATOR + moduleName)
                            .addModifiers(PUBLIC)
                            .addJavadoc(WARNING_TIPS)
                            .addMethod(loadIntoMethodOfTollgateBuilder.build())
                            .addSuperinterface(ClassName.get(type_ITollgateGroup))
                            .build()
            ).build().writeTo(mFiler);

        }
    }

    /**
     * 校验原始是不是被Interceptor注解,并且是IInterceptor子类
     *
     * @param element Interceptor taw type
     * @return verify result
     */
    private boolean verify(Element element) {
        Interceptor interceptor = element.getAnnotation(Interceptor.class);
        return null != interceptor && ((TypeElement) element).getInterfaces().contains(iInterceptor);
    }
}

主要生成一个按优先级添加IInterceptor列表的类,在ARouter.init()时通过此类将IInterceptor列表加载进内存。然后通过InterceptorService来进行拦截器管理。后续在详解InterceptorService

public class ARouter$$Interceptors$$模块名称 implements IInterceptorGroup{
    @Override
    public void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptor){
        interceptors.put(优先级,拦截器类信息);
    }
}

AutowiredProcessor

public class AutowiredProcessor extends BaseProcessor {
    /**
     * 需要自动装配的成员变量和它的父节点类列表<父节点类,当前类需要自动装配的成员变量列表>
     */
    private Map<TypeElement, List<Element>> parentAndChild = new HashMap<>(); 
@Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        if (CollectionUtils.isNotEmpty(set)) {
            try {
                logger.info(">>> Found autowired field, start... <<<");
                //遍历所有Autowired注解,并按父节点类加入列表
                categories(roundEnvironment.getElementsAnnotatedWith(Autowired.class));
                //根据父节点类列表生成对应装配类
                generateHelper();

            } catch (Exception e) {
                logger.error(e);
            }
            return true;
        }

        return false;
    }
/**
     * @throws IOException
     * @throws IllegalAccessException
     */
    private void generateHelper() throws IOException, IllegalAccessException {
        //...省略代码

        //创建参数Object target
        ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, "target").build();

        if (MapUtils.isNotEmpty(parentAndChild)) {
            //遍历parentAndChild
            for (Map.Entry<TypeElement, List<Element>> entry : parentAndChild.entrySet()) {
                /**
                 * 创建inject方法
                 * @Override
                 * public void inject(Object target)
                 */
                MethodSpec.Builder injectMethodBuilder = MethodSpec.methodBuilder(METHOD_INJECT)
                        .addAnnotation(Override.class)
                        .addModifiers(PUBLIC)
                        .addParameter(objectParamSpec);

                TypeElement parent = entry.getKey();
                List<Element> childs = entry.getValue();
                //获取父节点类的限定名
                String qualifiedName = parent.getQualifiedName().toString();
                //获取父节点类包名
                String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
                //父节点类对应装配器类名
                String fileName = parent.getSimpleName() + NAME_OF_AUTOWIRED;

                logger.info(">>> Start process " + childs.size() + " field in " + parent.getSimpleName() + " ... <<<");
                /**
                 * 创建装配器类
                 * public class 父节点类包名$$ARouter$$Autowired implements ISyringe{
                 *      public void inject(Object target){
                 *
                 *      }
                 * }
                 */
                TypeSpec.Builder helper = TypeSpec.classBuilder(fileName)
                        .addJavadoc(WARNING_TIPS)
                        .addSuperinterface(ClassName.get(type_ISyringe))
                        .addModifiers(PUBLIC);
                //创建变量 SerializationService serializationService,用来对Object变量进行序列化和反序列化
                FieldSpec jsonServiceField = FieldSpec.builder(TypeName.get(type_JsonService.asType()), "serializationService", Modifier.PRIVATE).build();
                helper.addField(jsonServiceField);
                //inject方法中添加初始化serializationService语句
                injectMethodBuilder.addStatement("serializationService = $T.getInstance().navigation($T.class)", ARouterClass, ClassName.get(type_JsonService));
                //inject方法中添加对参数target进行强制类型转换语句
                injectMethodBuilder.addStatement("$T substitute = ($T)target", ClassName.get(parent), ClassName.get(parent));

                // 遍历待装配变量列表
                for (Element element : childs) {
                    Autowired fieldConfig = element.getAnnotation(Autowired.class);
                    //获取装配变量名
                    String fieldName = element.getSimpleName().toString();
                    //如果变量类型是iProvider,这通过ARouter.getInstance().navigation(类),来进行装配
                    if (types.isSubtype(element.asType(), iProvider)) {  // It's provider
                        if ("".equals(fieldConfig.name())) {    // User has not set service path, then use byType.

                            // Getter
                            injectMethodBuilder.addStatement(
                                    "substitute." + fieldName + " = $T.getInstance().navigation($T.class)",
                                    ARouterClass,
                                    ClassName.get(element.asType())
                            );
                        } else {    // use byName
                            // Getter
                            injectMethodBuilder.addStatement(
                                    "substitute." + fieldName + " = ($T)$T.getInstance().build($S).navigation()",
                                    ClassName.get(element.asType()),
                                    ARouterClass,
                                    fieldConfig.name()
                            );
                        }

                        // Validater
                        if (fieldConfig.required()) {
                            injectMethodBuilder.beginControlFlow("if (substitute." + fieldName + " == null)");
                            injectMethodBuilder.addStatement(
                                    "throw new RuntimeException(\"The field '" + fieldName + "' is null, in class '\" + $T.class.getName() + \"!\")", ClassName.get(parent));
                            injectMethodBuilder.endControlFlow();
                        }
                    } else {    // It's normal intent value
                        String originalValue = "substitute." + fieldName;
                        String statement = "substitute." + fieldName + " = " + buildCastCode(element) + "substitute.";
                        boolean isActivity = false;
                        //如果是activity则通过getIntent()获取传递的数据
                        if (types.isSubtype(parent.asType(), activityTm)) {  // Activity, then use getIntent()
                            isActivity = true;
                            statement += "getIntent().";
                        } else if (types.isSubtype(parent.asType(), fragmentTm) || types.isSubtype(parent.asType(), fragmentTmV4)) {   // Fragment, then use getArguments()
                            //如果是fragment则通过getArguments()获取传递的数据
                            statement += "getArguments().";
                        } else {
                            throw new IllegalAccessException("The field [" + fieldName + "] need autowired from intent, its parent must be activity or fragment!");
                        }
                        //根据变量的不同类型,创建对应的获取语句
                        statement = buildStatement(originalValue, statement, typeUtils.typeExchange(element), isActivity);
                        if (statement.startsWith("serializationService.")) {   // Not mortals
                            injectMethodBuilder.beginControlFlow("if (null != serializationService)");
                            injectMethodBuilder.addStatement(
                                    "substitute." + fieldName + " = " + statement,
                                    (StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name()),
                                    ClassName.get(element.asType())
                            );
                            injectMethodBuilder.nextControlFlow("else");
                            injectMethodBuilder.addStatement(
                                    "$T.e(\"" + Consts.TAG + "\", \"You want automatic inject the field '" + fieldName + "' in class '$T' , then you should implement 'SerializationService' to support object auto inject!\")", AndroidLog, ClassName.get(parent));
                            injectMethodBuilder.endControlFlow();
                        } else {
                            injectMethodBuilder.addStatement(statement, StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name());
                        }

                        // Validator
                        if (fieldConfig.required() && !element.asType().getKind().isPrimitive()) {  // Primitive wont be check.
                            injectMethodBuilder.beginControlFlow("if (null == substitute." + fieldName + ")");
                            injectMethodBuilder.addStatement(
                                    "$T.e(\"" + Consts.TAG + "\", \"The field '" + fieldName + "' is null, in class '\" + $T.class.getName() + \"!\")", AndroidLog, ClassName.get(parent));
                            injectMethodBuilder.endControlFlow();
                        }
                    }
                }

                helper.addMethod(injectMethodBuilder.build());

                // 生成装配器类文件
                JavaFile.builder(packageName, helper.build()).build().writeTo(mFiler);
            }
        }
    }
}

主要是生成对应类的装配器,路径在\build\generated\ap_generated_sources\debug\out\对应包名\对应使用Autowired的类

public class 父节点类包名$$ARouter$$Autowired implements ISyringe{
    public void inject(Object target){
        //例如
        TestActivity substitute = (TestActivity )target;
        substitute.text =  substitute.getIntent().getIntExtra("text");
    }
}

然后在调用ARouter.getInstance().inject(this);时,通过AutowiredService管理类创建装配器类,然后进行变量装配。后面详解

初始化

ARouter初始化一般是在Application中调用ARouter.init(context);

public static void init(Application application) {
    if (!hasInit) {
        logger = _ARouter.logger;
        _ARouter.logger.info(Consts.TAG, "ARouter init start.");
        hasInit = _ARouter.init(application);
        if (hasInit) {
            _ARouter.afterInit();
        }
        _ARouter.logger.info(Consts.TAG, "ARouter init over.");
    }
}

最终会通过_ARouter.init(application)调用LogisticsCenter.init(mContext, executor)

public class LogisticsCenter {
    public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
        try {
            //...省略代码
            if (registerByPlugin) {
                logger.info(TAG, "Load router map by arouter-auto-register plugin.");
            } else {
                Set<String> routerMap;
                //...省略代码
                // 如果是debug版本或者app版本更新,就重新加载所有com.alibaba.android.arouter.routes.*文件路径,不然就从sp中获取,这样只有第一次慢一点
                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();
                    }

                    PackageUtils.updateVersion(context);    // Save new version name when router map update finishes.
                } else {
                    logger.info(TAG, "Load router map from cache.");
                    routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
                }

                logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
                startInit = System.currentTimeMillis();
                //变量所有的路由文件
                for (String className : routerMap) {
                    if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
                        //如果是GroupRoot,通过反射创建对象,并加载到Warehouse.groupsIndex列表中
                        // 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
                        //如果是拦截器Group,通过反射创建对象,并加载到Warehouse.interceptorsIndex列表中
                        ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
                    } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
                        // Load providerIndex
                        //如果是ProviderGroup,通过反射创建对象,并加载到Warehouse.providersIndex列表中
                        ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
                    }
                }
            }

            logger.info(TAG, "Load root element finished, cost " + (System.currentTimeMillis() - startInit) + " ms.");

            if (Warehouse.groupsIndex.size() == 0) {
                logger.error(TAG, "No mapping files were found, check your configuration please!");
            }

            if (ARouter.debuggable()) {
                logger.debug(TAG, String.format(Locale.getDefault(), "LogisticsCenter has already been loaded, GroupIndex[%d], InterceptorIndex[%d], ProviderIndex[%d]", Warehouse.groupsIndex.size(), Warehouse.interceptorsIndex.size(), Warehouse.providersIndex.size()));
            }
        } catch (Exception e) {
            throw new HandlerException(TAG + "ARouter init logistics center exception! [" + e.getMessage() + "]");
        }
    }
}

初始化主要完成了

  1. 扫描所有com.alibaba.android.arouter.routes.*文件路径,因为注解处理器生成的java文件都在这个路径下
  2. 通过反射创建对应对象
  3. 根据类型调用相应loadInfo方法加载到Warehouse中,Warehouse可以理解就是一个路由表。

_ARouter.init初始化完,注意调用了_ARouter.afterInit()

final class _ARouter {
    //...
    static void afterInit() {
        interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
    }
    //...
}

这里初始化了拦截器管理类,后面再详解如何创建及什么时候使用。

使用路由

路由的基本使用:ARouter.getInstance().build("app/main").withBoolean("state",true).navigation();

ARouter.build会直接调用_ARouter.getInstance().build(path),build有多个重载方法,build(string)、build(url),build(path、group),最后调用都一样,我们以build(string)为例。

final class _ARouter {
//...省略代码
    protected Postcard build(String path) {
        //判空
        if (TextUtils.isEmpty(path)) {
            throw new HandlerException(Consts.TAG + "Parameter is invalid!");
        } else {
            //获取路由替换服务,PathReplaceService就是一个IProvider,提供forString、forUrl对路由地址进行替换。获取过程后面详解。
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                //如果路由替换服务不为空,调用替换方法
                path = pService.forString(path);
            }
            //调用重载方法build(path,group)返回Postcard
            return build(path, extractGroup(path));
        }
    }
//...省略代码
}

在build(path)方法中首先会通过PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);获取我们自定义的PathReplaceService,例如:

@Route(path = "/app/replace")
public class MyPathReplaceService implements PathReplaceService {
    @Override
    public String forString(String path) {
        if(path.equals(ActivityConsts.ACTIVITY_URL_SECOND)){
            return ActivityConsts.ACTIVITY_URL_THIRD;
        }
        return path;
    }
    @Override
    public Uri forUri(Uri uri) {
        return null;
    }
    @Override
    public void init(Context context) {

    }
}

如果获取PathReplaceService不为空,则调用forString(path)对当前路由进行替换。我们先来看一下PathReplaceService的获取方式。PathReplaceService继承IProvider接口,所以它的获取方式IProvider的获取方式一样,所以后面所有获取IProvider都可以参考这个。一层层跟进,最后会调用

final class _ARouter {
    //...省略代码
    protected <T> T navigation(Class<? extends T> service) {
        try {
            //通过Warehouse.providersIndex表,根据class name获取Postcard
            Postcard postcard = LogisticsCenter.buildProvider(service.getName());

            // Compatible 1.0.5 compiler sdk.
            // Earlier versions did not use the fully qualified name to get the service
            if (null == postcard) {
                // No service, or this service in old version.
                postcard = LogisticsCenter.buildProvider(service.getSimpleName());
            }

            if (null == postcard) {
                return null;
            }
            //校验Postcard,添加相应属性,并通过反射创建相应IProvider对象
            LogisticsCenter.completion(postcard);
            return (T) postcard.getProvider();
        } catch (NoRouteFoundException ex) {
            logger.warning(Consts.TAG, ex.getMessage());
            return null;
        }
    }
    //...省略代码
}
  1. 根据class name从init时加载的Warehouse.providersIndex表中获取Postcard
  2. 使用LogisticsCenter.completion(postcard)方法校验Postcard,添加相应属性,并通过反射创建相应IProvider对象

跟进看一下LogisticsCenter.completion

public class LogisticsCenter {
    //...省略代码
    public synchronized static void completion(Postcard postcard) {
        if (null == postcard) {
            throw new NoRouteFoundException(TAG + "No postcard!");
        }
        //从Warehouse.routes路由表加载对应路由信息
        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
        //如果还未加载过对应路由
        if (null == routeMeta) {
            //先获取对应group分组
            Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup());
            //如果不存在对应分组,直接报错
            if (null == groupMeta) {
                throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
            } else {
                // Load route and cache it into memory, then delete from metas.
                try {
                    if (ARouter.debuggable()) {
                        logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] starts loading, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
                    }
                    //通过反射创建对应分组对象
                    IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
                    //将该分组下所有路由信息加载到Warehouse.routes
                    iGroupInstance.loadInto(Warehouse.routes);
                    //从分组列表中删除对应分组,避免多次加载
                    Warehouse.groupsIndex.remove(postcard.getGroup());

                    if (ARouter.debuggable()) {
                        logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] has already been loaded, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
                    }
                } catch (Exception e) {
                    throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
                }
                //重新调用completion
                completion(postcard);
            }
        } else {
            //如果已加载过对应路由,添加相应属性
            postcard.setDestination(routeMeta.getDestination());
            postcard.setType(routeMeta.getType());
            postcard.setPriority(routeMeta.getPriority());
            postcard.setExtra(routeMeta.getExtra());
            //如果是通过Uri获取路由
            Uri rawUri = postcard.getUri();
            if (null != rawUri) {
                //获取Uri中的参数,并根据Autowired注解变量的类型,将参数设置到Bundle中,用于后面变量的自动装配
                Map<String, String> resultMap = TextUtils.splitQueryParameters(rawUri);
                Map<String, Integer> paramsType = routeMeta.getParamsType();

                if (MapUtils.isNotEmpty(paramsType)) {
                    for (Map.Entry<String, Integer> params : paramsType.entrySet()) {
                        setValue(postcard,
                                params.getValue(),
                                params.getKey(),
                                resultMap.get(params.getKey()));
                    }
                    postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArray(new String[]{}));
                }
                postcard.withString(ARouter.RAW_URI, rawUri.toString());
            }

            switch (routeMeta.getType()) {
                case PROVIDER:
                    //如果是注解是PROVIDER类型
                    Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
                    //判断Warehouse.providers列表中是否已经创建了对应的IProvider
                    IProvider instance = Warehouse.providers.get(providerMeta);
                    if (null == instance) {
                        //如果没有创建,通过反射创建对应IProvider对象,并添加到Warehouse.providers列表中
                        IProvider provider;
                        try {
                            provider = providerMeta.getConstructor().newInstance();
                            provider.init(mContext);
                            Warehouse.providers.put(providerMeta, provider);
                            instance = provider;
                        } catch (Exception e) {
                            throw new HandlerException("Init provider failed! " + e.getMessage());
                        }
                    }
                    //对postcard中的IProvider进行赋值
                    postcard.setProvider(instance);
                    //设置IProvider不能被拦截
                    postcard.greenChannel();
                    break;
                case FRAGMENT:
                    postcard.greenChannel();
                default:
                    break;
            }
        }
    }
    //...省略代码
}
  1. 检查路由是否已经加载,如果加载了会放在Warehouse.routes表中
  2. 如果没有记载过此路由,先加载路由分组,通过反射创建分组对象,并将该分组下的所有路由加载到Warehouse.routes表,重新加载路由
  3. 根据路由信息更新postcard对应字段,Postcard下边详解
  4. 如果是通过Uri获取路由,需要根据参数类型将Uri中传递的参数加载到Postcard的Bundle中
  5. 如果是PROVIDER类型,则通过反射创建相应对象,调用IProvider.init方法进行初始化,并添加到Warehouse.providers表中
  6. 对Postcard的provider字段进行赋值,设置provider不能被拦截

Postcard可以理解为路由组装类,类似于builder模式

  1. 定义了activity跳转、fragment传递数据的Bundle,并提供设置参数的接口及Object序列化服务

  2. 支持设置activity跳转动画及启动模式

  3. 如果当前RouteMeta的类型是Iprovider,会提供provider实例

  4. greenChannel标记当前路由是否可以被拦截

    public final class Postcard extends RouteMeta {
    // Base
    private Uri uri;
    //传递数据
    private Bundle mBundle;
    //activity启动模式
    private int flags = -1;
    //拦截超时
    private int timeout = 300;
    //如果当前路由是IProvider,就会被设置
    private IProvider provider;
    //表示是否会被拦截,true不能被拦截
    private boolean greenChannel;
    //mBundle设置Object是序列化服务
    private SerializationService serializationService;

    //activity跳转动画
    private Bundle optionsCompat;    // The transition animation of activity
    private int enterAnim;
    private int exitAnim;
    //...省略代码
    public void navigation(Activity mContext, int requestCode, NavigationCallback callback) {
        ARouter.getInstance().navigation(mContext, this, requestCode, callback);
    }
    //...省略代码

    }

执行路由Postcard.navigation(),直接执行ARouter.getInstance().navigation(mContext, this, requestCode, callback);最终都会调用_ARouter.getInstance().navigation

final class _ARouter {
    /**
     * 执行路由
     *
     * @param context     Activity or null.
     * @param postcard    Route metas 路由
     * @param requestCode RequestCode activity请求码
     * @param callback    路由执行回调
     */
    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        //获取预处理服务,PretreatmentService就是一个IProvider,获取方式和PathReplaceService一样
        PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
        if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
            //预处理服务不为空,并且预处理失败,则不执行路由
            return null;
        }

        try {
            /**
             * 补全路由数据,由于build返回的Postcard对象,是我们手动填写的路由地址,但路由并不一定存在,
             * 所有通过LogisticsCenter.completion来校验是否存在此路由,并补全Postcard相关成员变量
             */
            LogisticsCenter.completion(postcard);
        } catch (NoRouteFoundException ex) {
            //路由不存在
            if (debuggable()) {
                // debug模式就Toast提醒
                runInMainThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(mContext, "There's no route matched!\n" +
                                " Path = [" + postcard.getPath() + "]\n" +
                                " Group = [" + postcard.getGroup() + "]", Toast.LENGTH_LONG).show();
                    }
                });
            }
            /**
             * 如果回调不为空,执行回调onLost,如果回调为空,执行降级策略,所有要注意设置了回调是不会执行降级策略的
             */
            if (null != callback) {
                callback.onLost(postcard);
            } else {
                //获取降级策略服务,DegradeService就是一个IProvider
                DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
                if (null != degradeService) {
                    degradeService.onLost(context, postcard);
                }
            }

            return null;
        }
        //回调onFound
        if (null != callback) {
            callback.onFound(postcard);
        }
        //是否能被拦截
        if (!postcard.isGreenChannel()) {
            //通过InterceptorService服务,检查是否被拦截
            interceptorService.doInterceptions(postcard, new InterceptorCallback() {
                /**
                 * 继续执行
                 * @param postcard route meta
                 */
                @Override
                public void onContinue(Postcard postcard) {
                    _navigation(context, postcard, requestCode, callback);
                }

                /**
                 * 被拦截
                 * @param exception Reson of interrupt.
                 */
                @Override
                public void onInterrupt(Throwable exception) {
                    if (null != callback) {
                        callback.onInterrupt(postcard);
                    }
                }
            });
        } else {
            //继续执行路由
            return _navigation(context, postcard, requestCode, callback);
        }

        return null;
    }

    private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        final Context currentContext = null == context ? mContext : context;

        switch (postcard.getType()) {
            //如果是Activity路由
            case ACTIVITY:
                // 创建Intent并添加数据
                final Intent intent = new Intent(currentContext, postcard.getDestination());
                intent.putExtras(postcard.getExtras());

                // 设置启动模式
                int flags = postcard.getFlags();
                if (-1 != flags) {
                    intent.setFlags(flags);
                } else if (!(currentContext instanceof Activity)) {
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                }

                // 设置action
                String action = postcard.getAction();
                if (!TextUtils.isEmpty(action)) {
                    intent.setAction(action);
                }

                // 在主线程启动activity
                runInMainThread(new Runnable() {
                    @Override
                    public void run() {
                        startActivity(requestCode, currentContext, intent, postcard, callback);
                    }
                });

                break;
            case PROVIDER:
                //如果是IProvider路由,直接返回
                return postcard.getProvider();
            case BOARDCAST:
            case CONTENT_PROVIDER:
            case FRAGMENT:
                /**
                 * 如果是BoardCast、ContentProvider、Fragment路由,通过反射调用无参数构造函数继续创建,
                 * 所有BoardCast、ContentProvider类型基本上没什么用
                 */
                Class fragmentMeta = postcard.getDestination();
                try {
                    Object instance = fragmentMeta.getConstructor().newInstance();
                    if (instance instanceof Fragment) {
                        ((Fragment) instance).setArguments(postcard.getExtras());
                    } else if (instance instanceof android.support.v4.app.Fragment) {
                        ((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());
                    }

                    return instance;
                } catch (Exception ex) {
                    logger.error(Consts.TAG, "Fetch fragment instance error, " + TextUtils.formatStackTrace(ex.getStackTrace()));
                }
            case METHOD:
            case SERVICE:
            default:
                return null;
        }

        return null;
    }
}
  1. 获取预处理服务PretreatmentService,如果预处理失败则结束路由执行。PretreatmentService获取方式和PathReplaceService一样
  2. LogisticsCenter.completion(postcard)校验路由,由于build返回的Postcard对象,是我们手动填写的路由地址,但路由并不一定存在,所有通过LogisticsCenter.completion来校验是否存在此路由,并补全Postcard相关成员变量
  3. 路由不存在,如果有设置回调,则执行onLost,否则获取降级策略DegradeService,并执行。所以要注意如果设置了回调就不会调用降级策略
  4. 路由存在,则校验路由类型,并根据不同类型执行

路由的执行过程到这就结束了。

路由拦截

通过前面分析我们知道,路由拦截是通过InterceptorService实现的,InterceptorService的初始化后 _ARouter.afterInit()进行

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

通过路由"/arouter/service/interceptor"获取InterceptorService的实例InterceptorServiceImpl,定义在arouter-api。由于InterceptorServiceImpl继承IProvider接口,在初始化后会调用对应init()方法。

@Route(path = "/arouter/service/interceptor")
public class InterceptorServiceImpl implements InterceptorService {
    private static boolean interceptorHasInit;
    private static final Object interceptorInitLock = new Object();
    @Override
    public void init(final Context context) {
        //异步加载拦截器
        LogisticsCenter.executor.execute(new Runnable() {
            @Override
            public void run() {
                //在ARouter.init中会将所有定义的interceptor加载到Warehouse.interceptorsIndex列表中
                //如果Warehouse.interceptorsIndex不为空
                if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
                    //遍历所有拦截器,由于Warehouse.interceptorsIndex是TreeMap类型,默认按key的默认顺序进行排序,而key是Integer类型,所以key越小,优先级越高。
                    for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()) {
                        Class<? extends IInterceptor> interceptorClass = entry.getValue();
                        try {
                            //通过反射创建IInterceptor对应实例
                            IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance();
                            //调用init进行初始化
                            iInterceptor.init(context);
                            //添加到Warehouse.interceptors列表
                            Warehouse.interceptors.add(iInterceptor);
                        } catch (Exception ex) {
                            throw new HandlerException(TAG + "ARouter init interceptor error! name = [" + interceptorClass.getName() + "], reason = [" + ex.getMessage() + "]");
                        }
                    }
                    //设置加载完成标志位
                    interceptorHasInit = true;

                    logger.info(TAG, "ARouter interceptors init over.");
                    //释放同步锁
                    synchronized (interceptorInitLock) {
                        interceptorInitLock.notifyAll();
                    }
                }
            }
        });
    }
}

InterceptorServiceImpl.init(context)主要是通过异步方式,按优先级加载所有的 interceptor:

  1. 遍历Warehouse.interceptorsIndex列表,由于Warehouse.interceptorsIndex是TreeMap类型,默认按key的默认顺序进行排序,key的类型是Integer,所以key越小,优先级越高
  2. 通过反射创建IInterceptor对应实例
  3. 调用init进行初始化,添加到Warehouse.interceptors列表

执行拦截doInterceptions

public class InterceptorServiceImpl implements InterceptorService {
    private static boolean interceptorHasInit;
    private static final Object interceptorInitLock = new Object();

    @Override
    public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
        //如果拦截器列表不为空
        if (null != Warehouse.interceptors && Warehouse.interceptors.size() > 0) {
            //等待拦截器列表初始化完成,10秒超时
            checkInterceptorsInitStatus();
            //如果超时后还未初始化完成,直接回调拦截
            if (!interceptorHasInit) {
                callback.onInterrupt(new HandlerException("Interceptors initialization takes too much time."));
                return;
            }
            //异步执行拦截
            LogisticsCenter.executor.execute(new Runnable() {
                @Override
                public void run() {
                    CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
                    try {
                        //通过interceptorCounter根据优先级串行调用拦截器,如果被拦截,取消interceptorCounter,继续执行interceptorCounter.await之后代码
                        _excute(0, interceptorCounter, postcard);
                        //等待遍历拦截器列表,如果interceptorCounter未减为0或者超时,则阻塞等待
                        interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);

                        if (interceptorCounter.getCount() > 0) {
                            //如果interceptorCounter.getCount() > 0,证明是超时唤醒
                            callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
                        } else if (null != postcard.getTag()) {    
                            //在路由被拦截时,会设置tag,所以null != postcard.getTag证明被拦截
                            callback.onInterrupt(new HandlerException(postcard.getTag().toString()));
                        } else {
                            //不拦截,继续执行
                            callback.onContinue(postcard);
                        }
                    } catch (Exception e) {
                        callback.onInterrupt(e);
                    }
                }
            });
        } else {
            //不拦截,继续执行
            callback.onContinue(postcard);
        }
    }
}
  1. 等待拦截器列表初始化完成,10秒超时
  2. 异步执行拦截,通过interceptorCounter根据优先级串行调用拦截器,如果被拦截,取消interceptorCounter,继续执行interceptorCounter.await之后代码
  3. 根据interceptorCounter.getCount判断执行拦截或超时

自动装配

使用@Autowired注解后,需要在使用之前会调用ARouter.getInstance().inject(this)来完成自动装配。

static void inject(Object thiz) {
        AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
        if (null != autowiredService) {
            autowiredService.autowire(thiz);
        }
}

自动装配主要是通过AutowiredService来进行管理的,通过“/arouter/service/autowired”路由获取到的是AutowiredServiceImpl。定义在arouter-api中

@Route(path = "/arouter/service/autowired")
public class AutowiredServiceImpl implements AutowiredService {
    /**
     * ISyringe缓存
     */
    private LruCache<String, ISyringe> classCache;
    /**
     * 黑名单,不能autowire的类名
     */
    private List<String> blackList;

    @Override
    public void autowire(Object instance) {
        String className = instance.getClass().getName();
        try {
            //不存在黑名单
            if (!blackList.contains(className)) {
                //获取缓存
                ISyringe autowiredHelper = classCache.get(className);
                if (null == autowiredHelper) {
                    //不存在缓存,通过反射创建对应装配器实例。前面我们说过AutowiredProcessor会为每个包含Autowired注解的类生成一个装配器类
                    autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
                }
                //进行装配
                autowiredHelper.inject(instance);
                //添加到缓存,避免多次创建
                classCache.put(className, autowiredHelper);
            }
        } catch (Exception ex) {
            //加入黑名单
            blackList.add(className);
        }
    }
}

主要通过反射创建对应AutowiredProcessor生成的装配器类,调用装配器类的inject进行注入。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器