ARouter 源码解析

本文详细解析了阿里巴巴的ARouter框架,介绍了ARouter的作用,包括页面跳转、通信和解耦。文章深入探讨了ARouter的编译期原理,通过APT生成路由表,并分析了运行时的初始化流程和路由执行流程,阐述了如何按需加载和实例化路由组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

最近使用了阿里的ARouter框架,现在来讲解一下自己关于ARouter源码的理解


一、ARouter 简介

1. 什么是ARouter

ARouter是由alibaba开源的一个帮助Android App进行组件化路由改造的路由框架。(Github地址)

2. ARouter框架的作用

  1. 路由:实现页面之间的跳转,包括外部URL跳转到内部页面,module之间页面跳转,可以监听跳转过程同时可以指定拦截器
  2. 通信:跳转时可以传递参数
  3. 解耦:跳转不再依赖具体的目标类,各个module之间耦合度降低

二、ARouter原理概述

ARouter功能的实现主要包含三个部分:1.配置和使用 2. 编译期 3. 运行时

1. 配置和使用

关于ARouter的使用方式,其实在GitHub中已经有很明确的介绍,我就不再赘述了。

2. 编译期原理分析

ARouter框架使用时主要用的三个编译期注解为@Route、@Interceptor、@Autowired,在代码的编译期间,利用APT(Annotation Processing Tool)工具生成路由表,对应的注解处理器分别为 RouteProcessor,InterceptorProcessor,AutowiredProcessor,都在arouter-compiler包中。他们都继承自BaseProcessor类,而BaseProcessor继承自AbstractProcessor类,利用Google的@AutoService(Processor.class)注解自动生成服务,当处于编译期间时,编译器会检测继承自AbstractProcessor的子类,调用子类的process()方法,并将包含注解的元素传递进来,然后经过分析后,使用JavaPoet生成java文件。

我们先看一下BaseProcessor类的关键方法,

BaseProcessor.java

//初始化方法,只会执行一次
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
    super.init(processingEnv);
   
    //用于生成.java文件
    mFiler = processingEnv.getFiler();
    //类型校验
    types = processingEnv.getTypeUtils();
    //元素校验
    elementUtils = processingEnv.getElementUtils();
    //类型工具类
    typeUtils = new TypeUtils(types, elementUtils);
    //封装了日志
    logger = new Logger(processingEnv.getMessager());

    // Attempt to get user configuration [moduleName]
    Map<String, String> options = processingEnv.getOptions();
    //读取我们在build.gradle中配置的信息
    if (MapUtils.isNotEmpty(options)) {
        moduleName = options.get(KEY_MODULE_NAME);
        generateDoc = VALUE_ENABLE.equals(options.get(KEY_GENERATE_DOC_NAME));
    }

    if (StringUtils.isNotEmpty(moduleName)) {
        moduleName = moduleName.replaceAll("[^0-9a-zA-Z_]+", "");
        logger.info("The user has configuration the module name, it was [" + moduleName + "]");
    } else {
        //如果没配置会报出异常
        logger.error(NO_MODULE_NAME_TIPS);
        throw new RuntimeException("ARouter::Compiler >>> No module name, for more information, look at gradle log.");
    }
}

@Override
public Set<String> getSupportedOptions() {
    //添加Option参数,在build.gradle中配置
    return new HashSet<String>() {{
        this.add(KEY_MODULE_NAME);
        this.add(KEY_GENERATE_DOC_NAME);
    }};
}

BaseProcessor中定义了一些基本的方法,下面我们通过RouteProcessor分析ARouter如何生成路由文件的。

RouteProcessor.java

@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
    super.init(processingEnv);
    //如果需要生成文档,初始化JavaFile对象,在build.gradle中配置
    if (generateDoc) {
        try {
            docWriter = mFiler.createResource(
                    StandardLocation.SOURCE_OUTPUT,
                    PACKAGE_OF_GENERATE_DOCS,
                    "arouter-map-of-" + moduleName + ".json"
            ).openWriter();
        } catch (IOException e) {
            logger.error("Create doc writer failed, because " + e.getMessage());
        }
    }
    ......
}

//会自动被编译器调用
@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... <<<");
            //解析路由
            this.parseRoutes(routeElements);
        } catch (Exception e) {
            logger.error(e);
        }
        return true;
    }
    return false;
}

//解析数据,组合rootMap、groupMap,生成ARouter$$Group$$xxx,ARouter$$Providers$$xxx,ARouter$$Root$$xxx文件
private void parseRoutes(Set<? extends Element> routeElements) throws IOException {
    if (CollectionUtils.isNotEmpty(routeElements)) {
        rootMap.clear();
        
        TypeMirror type_Activity = elementUtils.getTypeElement(ACTIVITY).asType();
        TypeMirror type_Service = elementUtils.getTypeElement(SERVICE).asType();
        TypeMirror fragmentTm = elementUtils.getTypeElement(FRAGMENT).asType();
        TypeMirror fragmentTmV4 = elementUtils.getTypeElement(Consts.FRAGMENT_V4).asType();

        // Interface of ARouter
        TypeElement type_IRouteGroup = elementUtils.getTypeElement(IROUTE_GROUP);
        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)
        );

		//构建com.alibaba.android.arouter.routes包下的
		//ARouter$$Group$$xxx,ARouter$$Providers$$xxx,ARouter$$Root$$xxx,三个文件的方法入参
        ParameterSpec rootParamSpec = ParameterSpec.builder(inputMapTypeOfRoot, "routes").build();
        ParameterSpec groupParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "atlas").build();
        ParameterSpec providerParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "providers").build();//构建ARouter$$Root$$xxx的loadInto方法
        MethodSpec.Builder loadIntoMethodOfRootBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
                .addAnnotation(Override.class)
                .addModifiers(PUBLIC)
                .addParameter(rootParamSpec);
                
		//for循环解析各种元素,生成不同的RouteMeta
        for (Element element : routeElements) {
            TypeMirror tm = element.asType();
            Route route = element.getAnnotation(Route.class);
            RouteMeta routeMeta;
            // Activity or Fragment
            if (types.isSubtype(tm, type_Activity) || types.isSubtype(tm, fragmentTm) || types.isSubtype(tm, fragmentTmV4)) {
                // Get all fields annotation by @Autowired
                Map<String, Integer> paramsType = new HashMap<>();
                Map<String, Autowired> injectConfig = new HashMap<>();
                injectParamCollector(element, paramsType, injectConfig);
                if (types.isSubtype(tm, type_Activity)) {
                    // Activity
                    routeMeta = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType);
                } else {
                    // Fragment
                    routeMeta = new RouteMeta(route, element, RouteType.parse(FRAGMENT), paramsType);
                }
                routeMeta.setInjectConfig(injectConfig);
            } else if (types.isSubtype(tm, iProvider)) {         // IProvider
                routeMeta = new RouteMeta(route, element, RouteType.PROVIDER, null);
            } else if (types.isSubtype(tm, type_Service)) {           // Service
                routeMeta = new RouteMeta(route, element, RouteType.parse(SERVICE), null);
            } else {
                throw new RuntimeException("The @Route is marked on unsupported class, look at [" + tm.toString() + "].");
            }
			
			//处理RouteMeta类型
            categories(routeMeta);
        }

		//ARouter$$Providers$$xxx文件的loadInto方法
        MethodSpec.Builder loadIntoMethodOfProviderBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
                .addAnnotation(Override.class)
                .addModifiers(PUBLIC)
                .addParameter(providerParamSpec);

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

        for (Map.Entry<String, Set<RouteMeta>> entry : groupMap.entrySet()) {
            String groupName = entry.getKey();

			//构建各个ARouter$$Group$$xxx文件的loadInto()
            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());
                switch (routeMeta.getType()) {
                    case PROVIDER:  // Need cache provider's super class
                        List<? extends TypeMirror> interfaces = ((TypeElement) routeMeta.getRawType()).getInterfaces();
                        for (TypeMirror tm : interfaces) {
                            routeDoc.addPrototype(tm.toString());

                            if (types.isSameType(tm, iProvider)) { 
                                // This interface extend the IProvider, so it can be used for mark provider
                                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)) {
                                // This interface extend the IProvider, so it can be used for mark provider
                                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;
                }

                // Make map body for paramsType
                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();
				
				//构建ARouter$$Group$$xxx组文件loadInto()的方法体
                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);
            }

            //生成各个ARouter$$Group$$xxx组文件
            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);

            rootMap.put(groupName, groupFileName);
            docSource.put(groupName, routeDocList);
        }

        //构建ARouter$$Root$$xxx文件,loadInto()的方法体
        if (MapUtils.isNotEmpty(rootMap)) {
            for (Map.Entry<String, String> entry : rootMap.entrySet()) {
                loadIntoMethodOfRootBuilder.addStatement("routes.put($S, $T.class)", entry.getKey(), ClassName.get(PACKAGE_OF_GENERATE_FILE, entry.getValue()));
            }
        }

        //生成Doc文件
        if (generateDoc) {
            docWriter.append(JSON.toJSONString(docSource, SerializerFeature.PrettyFormat));
            docWriter.flush();
            docWriter.close();
        }

		//生成ARouter$$Providers$$xxx文件
        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);

        //生成ARouter$$Root$$xxx文件
        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);
    }
}

//区分类型,组装groupMap
private void categories(RouteMeta 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);
            //处理同一Group的数据
            groupMap.put(routeMete.getGroup(), routeMetaSet);
        } else {
            routeMetas.add(routeMete);
        }
    } else {
        logger.warning(">>> Route meta verify error, group is " + routeMete.getGroup() + " <<<");
    }
}

同理,InterceptorProcessor 和 AutowiredProcessor 也是同样的原理生成对应的文件,我就不再重复解释了。

3. 运行时原理分析

当我们了解了编译期Arouter干了些什么之后,让我们来看看运行时的原理又是怎么样的。

1) 初始化流程
Application.java

if (BuildConfig.DEBUG) {
    ARouter.openLog();
    ARouter.openDebug();
}
ARouter.init(this);
ARouter.java

public static void init(Application application) {
    if (!hasInit) {
        logger = _ARouter.logger;
        _ARouter.logger.info(Consts.TAG, "ARouter init start.");
        //转移给_ARouter类去初始化
        hasInit = _ARouter.init(application);

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

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

protected static synchronized boolean init(Application application) {
    mContext = application;
    //转给LogisticsCenter去初始化
    LogisticsCenter.init(mContext, executor);
    logger.info(Consts.TAG, "ARouter init success!");
    hasInit = true;
    mHandler = new Handler(Looper.getMainLooper());
    return true;
}
LogisticsCenter.java

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

    try {
        long startInit = System.currentTimeMillis();
        //load by plugin first
        loadRouterMap();
        if (registerByPlugin) {
            logger.info(TAG, "Load router map by arouter-auto-register plugin.");
        } else {
            Set<String> routerMap;

            // It will rebuild router map every times when debuggable.
            if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
                logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
                // These class was generated by arouter-compiler.
                // 根据包名"com.alibaba.android.arouter.routes"去所有的dex文件中获取符合要求的.class文件集合
                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.");
                // 非debug模式走缓存
                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();

         	// 区分是Rout类型、Interceptor类型还是Provider类型,然后实例化类,调用loadInfo方法,将数据缓存到Warehouse的静态集合对象中
            for (String className : routerMap) {
                if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
                    // This one of root elements, load root.
                    ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
                } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
                    // Load interceptorMeta
                    ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
                } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
                    // Load providerIndex
                    ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
                }
            }
        }
        ......
    } catch (Exception e) {
        throw new HandlerException(TAG + "ARouter init logistics center exception! [" + e.getMessage() + "]");
    }
}

我们进入init方法中会发现实际的初始化操作交给了_ARouter类来操作,这么做的目的是为了让用户用起来更加方便,只对用户暴露他们实际需要用的API即可。在_ARouter中又将init转到了LogisticsCenter类中,通过源码我们可以发现LogisticsCenter的init的作用如下

  1. 扫描所有dex文件下com.alibaba.android.arouter.routes目录
  2. 加载所有模块下管理路由组Root文件
  3. 加载所有模块下管理服务的providers文件
  4. 加载所有模块下管理拦截器的intercepter文件
  5. 将加载的文件内容缓存到Warehouse类中,注意:此时并没有加载各个路由组、服务和拦截器文件,只是将组的信息加载到内容中,当真正需要用到路由、服务、拦截器的时候,按需加载
2) 路由执行流程

拿以下代码为例

ARouter.getInstance()
      .build("/demo/banner") //路径信息
      .withInt("count", 2) //参数信息
      .greenChannel() //绿色通道,可以跳过拦截器
      .navigation(); //导航

首先,调用build方法,会发现又是转交给_ARouter类去操作了,最后生成一个Postcard对象

_ARouter.java

/**
 * Build postcard by path and default group
 */
protected Postcard build(String path) {
    if (TextUtils.isEmpty(path)) {
        throw new HandlerException(Consts.TAG + "Parameter is invalid!");
    } else {
        // 如果我们实现了PathReplaceService接口,可以替换url,默认是null,这是ARouter提供给我们的第一个拦截处理路由的方式
        PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
        if (null != pService) {
            path = pService.forString(path);
        }
        // 调用build()方法,extractGroup是用来获取组名
        return build(path, extractGroup(path), true);
    }
}

/**
 * Build postcard by path and group
 */
protected Postcard build(String path, String group, Boolean afterReplace) {
    if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
        throw new HandlerException(Consts.TAG + "Parameter is invalid!");
    } else {
        if (!afterReplace) {
        	// 再次判断是否需要替换url路径
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                path = pService.forString(path);
            }
        }
        //生成对应的Postcard对象
        return new Postcard(path, group);
    }
}

Postcard是RouteMeta的子类,除了路由信息外,还包含了其他操作信息

Postcard.java

// Base
private Uri uri;
private Object tag;             // A tag prepare for some thing wrong. inner params, DO NOT USE!
private Bundle mBundle;         // Data to transform
private int flags = 0;         // Flags of route
private int timeout = 300;      // Navigation timeout, TimeUnit.Second
private IProvider provider;     // It will be set value, if this postcard was provider.
private boolean greenChannel;
private SerializationService serializationService;
private Context context;        // May application or activity, check instance type before use it.
private String action;

// Animation
private Bundle optionsCompat;    // The transition animation of activity
private int enterAnim = -1;
private int exitAnim = -1;

当我们通过各种方法设置完参数之后,调用navigation()方法去实现跳转,最终发现还是调用的_ARouter的navigation方法来实现,如下:

_ARouter.java

/**
 * Use router navigation.
 *
 * @param context     Activity or null.
 * @param postcard    Route metas
 * @param requestCode RequestCode
 * @param callback    cb
 */
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
    //首先判断我们是否实现了PretreatmentService接口,在这里我们可以在navigation前执行一些自己的代码
    PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
    if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
        // Pretreatment failed, navigation canceled.
        return null;
    }

    // Set context to postcard.
    postcard.setContext(null == context ? mContext : context);

    try {
        //调用LogisticsCenter的completion方法,去实例化需要用到路由组,并完善Postcard的信息
        LogisticsCenter.completion(postcard);
    } catch (NoRouteFoundException ex) {
        logger.warning(Consts.TAG, ex.getMessage());

        if (null != callback) {
            callback.onLost(postcard);
        } else {
            // No callback for this invoke, then we use the global degrade service.
            // 如果没有回调,如果我们实现了DegradeService降级策略,会执行我们的降级代码
            DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
            if (null != degradeService) {
                degradeService.onLost(context, postcard);
            }
        }

        return null;
    }

    if (null != callback) {
        callback.onFound(postcard);
    }

    if (!postcard.isGreenChannel()) {   // It must be run in async thread, maybe interceptor cost too mush time made ANR.
        //如果不是绿色通道,需要执行拦截器操作
        interceptorService.doInterceptions(postcard, new InterceptorCallback() {
            /**
             * Continue process
             *
             * @param postcard route meta
             */
            // 未拦截,继续执行_navigation()
            @Override
            public void onContinue(Postcard postcard) {
                _navigation(postcard, requestCode, callback);
            }

            /**
             * Interrupt process, pipeline will be destory when this method called.
             *
             * @param exception Reson of interrupt.
             */
            // 跳转被拦截
            @Override
            public void onInterrupt(Throwable exception) {
                if (null != callback) {
                    callback.onInterrupt(postcard);
                }

                logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
            }
        });
    } else {
        // 绿色通道直接执行_navigation
        return _navigation(postcard, requestCode, callback);
    }

    return null;
}

// navigation操作
private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
    final Context currentContext = postcard.getContext();

	// 判断Postcard的type类型
    switch (postcard.getType()) {
    	//如果是Activity类型,组装Intent对象,实现跳转
        case ACTIVITY:
            // Build intent
            final Intent intent = new Intent(currentContext, postcard.getDestination());
            intent.putExtras(postcard.getExtras());

            // Set flags.
            int flags = postcard.getFlags();
            if (0 != flags) {
                intent.setFlags(flags);
            }

            // Non activity, need FLAG_ACTIVITY_NEW_TASK
            if (!(currentContext instanceof Activity)) {
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }

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

            // Navigation in main looper.
            runInMainThread(new Runnable() {
                @Override
                public void run() {
                    startActivity(requestCode, currentContext, intent, postcard, callback);
                }
            });

            break;
        //如果是服务类型,返回服务对象
        case PROVIDER:
            return postcard.getProvider();
        //如果是广播、内容提供器、Fragment类型,实例化对象并返回
        case BOARDCAST:
        case CONTENT_PROVIDER:
        case FRAGMENT:
            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;
}

看一下路由组是如何实例化的

LogicticsCenter.java

/**
 * Completion the postcard by route metas
 *
 * @param postcard Incomplete postcard, should complete by this method.
 */
// 完善Postcard的信息
public synchronized static void completion(Postcard postcard) {
    if (null == postcard) {
        throw new NoRouteFoundException(TAG + "No postcard!");
    }

    //根据路径获取路由实例对象
    RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
    //如果没有实例化时
    if (null == routeMeta) { 
        // Maybe its does't exist, or didn't load.
        // 如果匹配不到信息,则报错
        if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) {
            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 {
				......
				//实例化路由组并缓存到Warehouse.routes中,并从Warehouse.groupsIndex移除该组
                addRouteGroupDynamic(postcard.getGroup(), null);
				......
            } catch (Exception e) {
                throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
            }
            // 重复调用,此时路由组已实例化
            completion(postcard);   // Reload
        }
    } else {
        //配置Postcard信息
        postcard.setDestination(routeMeta.getDestination());
        postcard.setType(routeMeta.getType());
        postcard.setPriority(routeMeta.getPriority());
        postcard.setExtra(routeMeta.getExtra());

        Uri rawUri = postcard.getUri();
        if (null != rawUri) {   // Try to set params into bundle.
            Map<String, String> resultMap = TextUtils.splitQueryParameters(rawUri);
            Map<String, Integer> paramsType = routeMeta.getParamsType();

            if (MapUtils.isNotEmpty(paramsType)) {
                // Set value by its type, just for params which annotation by @Param
                for (Map.Entry<String, Integer> params : paramsType.entrySet()) {
                    setValue(postcard,
                            params.getValue(),
                            params.getKey(),
                            resultMap.get(params.getKey()));
                }

                // Save params name which need auto inject.
                postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArray(new String[]{}));
            }

            // Save raw uri
            postcard.withString(ARouter.RAW_URI, rawUri.toString());
        }

        switch (routeMeta.getType()) {
            //如果是服务类型,实例化Provider并设置绿色通道
            case PROVIDER:  // if the route is provider, should find its instance
                // Its provider, so it must implement IProvider
                Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
                IProvider instance = Warehouse.providers.get(providerMeta);
                if (null == instance) { // There's no instance of this provider
                    IProvider provider;
                    try {
                        provider = providerMeta.getConstructor().newInstance();
                        provider.init(mContext);
                        Warehouse.providers.put(providerMeta, provider);
                        instance = provider;
                    } catch (Exception e) {
                        logger.error(TAG, "Init provider failed!", e);
                        throw new HandlerException("Init provider failed!");
                    }
                }
                postcard.setProvider(instance);
                postcard.greenChannel();    // Provider should skip all of interceptors
                break;
            //如果是Fragment类型,设置绿色通道
            case FRAGMENT:
                postcard.greenChannel();    // Fragment needn't interceptors
            default:
                break;
        }
    }
}

以上就是对路由过程的解析,我们可以大体按照下图来总结一下
在这里插入图片描述

个人理解,如有问题,请指正

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ByeMoon丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值