ARouter使用及原理分析

简介

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进行注入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值