ARouter 源码分析

一、前言

在开始分析ARouter的源码之前,我假定你已经知道ARouter 的用途,并且会熟练使用。下面我在官方demo的基础上,来分析每项功能的流程。

ARouter Github地址

demo 中的 三个 Module

  • app demo项目的 主module
  • module-java demo项目的 子module
  • module-kotlin demo项目的 子module

下面三个Module 提供了核心功能

  • arouter-annotation 使用到的注解相关信息,例如:@Route, @Interceptor,RouteMeta 等
  • arouter-api 主要的代码逻辑
  • arouter-complier 处理注解,生成相应的类。(你可能需要在编译期调试注解处理器

下面两个module 是方便ARouter的使用以及开发

  • arouter-gradle-plugin 进行路由表的自动加载, 默认通过扫描 dex 的方式 进行加载通过 gradle 插件进行自动注册可以缩短初始化时间解决应用加固导致无法直接访问 dex 文件。使用到字节码插桩相关知识
  • arouter-idea-plugin idea 插件,可以在跳转代码的行首找到一个图标 (navigation) 点击该图标,即可跳转到标识了代码中路径的目标类(在插件市场中搜索 ARouter Helper)。

我们在本篇的分析过程中,我们只分析主流程。涉及到类生成,字节码插桩 插入的函数,我们直接查看对应的类即可。它们的生成过程,后续分析

二、 arouter-annotation源码分析

2.1 @Route路由注解

@Route 是 声明路由的注解,主要用于描述路由中的路径URL信息,使用该注解标注的类将被自动添加至路由表中。

该注解可用于继承了 Activity,Fragment,IProvider(Ioc的接口,下文会介绍)的等子类上,在经过arouter-complier处理后,生成类的命名方式会有所不同

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Route {

    //路径URL字符串
    String path();

    //组名,默认为一级路径名;一旦被设置,跳转时必须赋值
    String group() default "";

    //该路径的名称,用于产生JavaDoc
    String name() default "undefined";

    //额外配置的开关信息;譬如某些页面是否需要网络校验、登录校验等
    int extras() default Integer.MIN_VALUE;

    //该路径的优先级
    int priority() default -1;
}

2.2 @Interceptor拦截器注解

@Interceptor 是拦截器注解,拦截器是全应用全局的。可设置优先级,对所有路由都生效

该注解用于实现IInterceptor 的类上

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Interceptor {
    /**
     * The priority of interceptor, ARouter will be excute them follow the priority.
     */
    int priority();

    /**
     * The name of interceptor, may be used to generate javadoc.
     */
    String name() default "Default";
}

2.3 @Autowired

@Autowired 是给变量自动赋值的。可以在界面跳转的时候参数传递,也可当做依赖注入

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.CLASS)
public @interface Autowired {

    // Mark param's name or service name.
    //如果指定的是service名称,就是在当做依赖注入使用
    String name() default "";

    // If required, app will be crash when value is null.
    // Primitive type wont be check!
    boolean required() default false;

    // Description of the field
    String desc() default "";
}

2.4 RouteMeta路由元信息

每一条路由,都对应一个RouteMeta对象

public class RouteMeta {
    private RouteType type;         // 路由的类型:
    private Element rawType;        // Raw type of route
    private Class<?> destination;   // 目标Class,最终就是根据这个参数反射得到对应的对象
    private String path;            // 路径URL
    private String group;           // 分组,路由都是有分组的,如果没有特别指定,默认第一个项是分组名称
    private int priority = -1;      // 路由的优先级
    private int extra;              // 目标Class的额外配置开关信息;譬如某些页面是否需要网络校验、登录校验等
    private Map<String, Integer> paramsType;  // 目标Class的需要注入的参数 的参数名称:参数类型TypeKind
}

三、arouter-compiler 生成的类介绍

下图是官方demo,编译后生成的类
在这里插入图片描述

  • routes 文件中,主要是注解@Route、@Interceptor生成的类,这些类负责加载路由目标类、拦截器、Provider等等
  1. 分组的路由表 ——工程名$$Group$$分组名 继承了 IRouteGroup

    • 每一个路径对应一个RouteMeta对象
    • 默认以“/xx/xx”的第一个xx为分组名
  2. 根路由——工程名$$Root$$模块名 继承了 IRouteRoot

    • 每个分组名,对应各自的分组路由表
    • ARouter在初始化的时候只会一次性地加载所有的root结点,而不会加载任何一个Group结点,当某一个分组下的某一个页面第一次被访问的时候,整个分组的全部页面都会被加载进去
  3. Ioc 路由表——工程名$$Providers$$模块名 继承了 IProviderGroup

    • 每一个实现了IProvider的接口 对应一个RouteMeta 对象,RouteMeta 对象的destination值 是 该接口的实现类
    • Ioc动作路由清单其实只是 Route注解的一种特殊用法,也是一种URL与目标类的映射关系
  4. 拦截器——工程名$$Interceptors$$模块名 继承了 ISyringe

    • 包含了某个模块下的拦截器 与 优先级的映射关系
  • 项目目录testactivity下,是使用@Autowired 注解后,生成的类——类名$$工程名$$Autowired 继承了 IRouteRoot
    • 所有使用了Autowired 的变量所在的类,会自动这种类,主要作用就是为类里的变量赋值 (做过后台开发的应该比较熟悉)

注意,这些自动生成的类,都继承了arouter-api 中的相关接口,下文会分析这些接口在何时被调用

四、arouter-api 源码流程分析

下图摘自
在这里插入图片描述
先来整体认识一下,这个module

  • 最上层是Launcher层,这一层是开发者可以直接用到的,其实所有的API都是在这一层中。

  • 接着是Frossard层,从上图中可以看到Frossard层也是绿色的,表示这一层也是可以被外部调用的,Frossard层其实包含了三部分,分别是:Service、Callback和Template.

    • 这里的Service概念和服务端的Service概念是相似的,也是在客户端的简单引申,但是却不同于Android组件中的Service,这里的Service是ARouter抽象出来的概念,从本质上讲,这里的Service是接口,从意义上讲是将一定的功能和组件封装成接口,并对外提供能力。
    • Template则是模板。Compiler模块在编译期会生成一些映射文件,而这些映射文件的生成规则就是根据Template来生成的,通过记录Template的相关接口函数名称+参数等,生成加载逻辑的代码,这样按照一定的规则和约束生成映射文件也方便Route在运行的时候进行读取。
  • 再往下一层就完全是SDK的内部实现了,这一层包括了Ware House、Thread、Log、Exception以及Class工具。

    • Ware House主要存储了ARouter在运行期间加载的路由、拦截器、分组等;
    • Thread 提供了线程池,因为存在多个拦截器的时候以及跳转过程中都是需要异步执行的;
    • Class 获取包名、资源名、系统等。
  • Logistics Center,从名字上翻译就是物流中心,整个SDK的流转以及内部调用最终都会下沉到这一层

下面就从一个简单的使用,来逐步深入源码

ARouter.init(getApplication());

4.1、初始化

ARouter 的所有函数的实现,都交给了_ARouter,先初始化_ARouter

   
    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/service/interceptor"
                //因为这个流程与界面跳转的流程,基本一致,所以这里暂不分析,可参考4.2 的分析
                _ARouter.afterInit();
            }

            _ARouter.logger.info(Consts.TAG, "ARouter init over.");
        }
    }
protected static synchronized boolean init(Application application) {
    mContext = application;
    //初始化LogisticsCenter,就是把编译器生成的那些路由信息加载,此时之后加载root路由、拦截器、provides
    LogisticsCenter.init(mContext, executor);
    hasInit = true;
    mHandler = new Handler(Looper.getMainLooper());

    return true;
}
LogisticsCenter类
   public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
        mContext = context;
        executor = tpe;
        try {
            //下面会重点分析这个方法
            loadRouterMap();
            //判断是否由自动生成的代码注册,这里自动生成的代码是指通过arouter-register项目使用 字节码插桩 添加的代码,
            //它们的功能是初始化各个module中的root路由、拦截器、provides。
            if (registerByPlugin) {
                //如果为true,就说明在loadRouterMap()中已经初始化了
                logger.info(TAG, "Load router map by arouter-auto-register plugin.");
            } else {
                //通过下面的代码初始化
                //com.alibaba.android.arouter.routes 路径下的所有类名称会被添加到这个变量中
                Set<String> routerMap;
					
                // It will rebuild router map every times when debuggable.
                if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {

                    // These class was generated by arouter-compiler.
                    //查找com.alibaba.android.arouter.routes 路径下的所有类(该路径就是第三点分析的routes文件夹)
                    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 {

                    routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
                }

                //根据不同的类名,强制转为不同的类型,进行初始化
                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() + "]");
        }
    }

arouter-register项目使用 字节码插桩 添加的代码,就是添加到函数loadRouterMap()中,去加载所有module下的com.alibaba.android.arouter.routes的root路由、拦截器、provides,会调用到register函数中

LogisticsCenter类
    private static void loadRouterMap() {
        registerByPlugin = false;
        //auto generate register code by gradle plugin: arouter-auto-register
        // looks like below:
        // registerRouteRoot(new ARouter..Root..modulejava());
        // registerRouteRoot(new ARouter..Root..modulekotlin());
    }

    private static void register(String className) {
        if (!TextUtils.isEmpty(className)) {
            try {
                Class<?> clazz = Class.forName(className);
                Object obj = clazz.getConstructor().newInstance();
                //上文说过,这些自动生成的类,都继承了atouter-api的相关接口,这里根据接口类型,进行不同的初始化
                if (obj instanceof IRouteRoot) {
                    registerRouteRoot((IRouteRoot) obj);
                } else if (obj instanceof IProviderGroup) {
                    registerProvider((IProviderGroup) obj);
                } else if (obj instanceof IInterceptorGroup) {
                    registerInterceptor((IInterceptorGroup) obj);
                } else {
                    logger.info(TAG, "register failed, class name: " + className
                            + " should implements one of IRouteRoot/IProviderGroup/IInterceptorGroup.");
                }
            } catch (Exception e) {
                logger.error(TAG,"register class error:" + className);
            }
        }
    }

这里只分析加载根路由的过程,registerProvider、registerInterceptor过程与它类似

    private static void registerRouteRoot(IRouteRoot routeRoot) {
        //把registerByPlugin 设置为true
        markRegisteredByPlugin();
        if (routeRoot != null) {
            //调用根路由的loadInto 函数,路由组信息加载到Warehouse.groupsIndex
            routeRoot.loadInto(Warehouse.groupsIndex);
        }
    }

这里以demo中主module的根路由为例

public class ARouter$$Root$$app implements IRouteRoot {
  @Override
  public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
     // 以路由组名 为key,对应的类class 为值,存入Warehouse.groupsIndex
    routes.put("test", ARouter$$Group$$test.class);
    routes.put("yourservicegroupname", ARouter$$Group$$yourservicegroupname.class);
  }
}

4.2、ARouter#build

下面从这行代码,来分析主流程

ARouter.getInstance().build("/test/activity2").navigation();

getInstance 获取ARouter的单例,就不用多说了,直接从build 开始分析

    protected Postcard build(String path) {
        if (TextUtils.isEmpty(path)) {
            throw new HandlerException(Consts.TAG + "Parameter is invalid!");
        } else {
           // 这里的navigation 就是根据 by type 获取Provide 的方式
           // 下文会介绍 by type 获取Provide 的源码
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
               //如果是实现了,这个Provide,就表示需要对路径进行替换
                path = pService.forString(path);
            }
            return build(path, extractGroup(path), true);
        }
    }
    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) {
                PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
                if (null != pService) {
                    path = pService.forString(path);
                }
            }
            //创建Postcard 对象,一个Postcard 对象就对应了一次路由请求,该对象作用于本次路由全过程
            return new Postcard(path, group);
        }
    }

4.3、Postcard#navigation

Postcard类
    public void navigation(Activity mContext, int requestCode, NavigationCallback callback) {
        ARouter.getInstance().navigation(mContext, this, requestCode, callback);
    }
ARouter类
    public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) {
        //又调用到_ARouter 中
        return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
    }

4.4、_ARouter#navigation

    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        //获取预处理的Provide
        PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
        //如果不为空,就执行
        if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
            // Pretreatment failed, navigation canceled.
            return null;
        }

        try {
           // 加载本次路由的路由组,并设置关于路由的更多信息到postcard
            LogisticsCenter.completion(postcard);
        } catch (NoRouteFoundException ex) {
			//如果没有 对应路由的元数据,就抛出异常,也就是降级处理
            if (null != callback) {
                //如果设置了,回调,元器件 也是单独降级处理
                callback.onLost(postcard);
            } else {
                // No callback for this invoke, then we use the global degrade service.
                //通过by type 的方式获取DegradeService 实例,进行降级处理,这是全局降级
                DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
                if (null != degradeService) {
                    degradeService.onLost(context, postcard);
                }
            }

            return null;
        }
		//如果在调用 navigation 的时候,设置了回调函数
        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
                 */
                @Override
                public void onContinue(Postcard postcard) {
                   //拦截器的处理结果是继续
                    _navigation(context, postcard, requestCode, callback);
                }

                /**
                 * Interrupt process, pipeline will be destory when this method called.
                 *
                 * @param exception Reson of interrupt.
                 */
                @Override
                public void onInterrupt(Throwable exception) {
                   //拦截器的处理结果是中断
                   //如果在调用 navigation 的时候,设置了回调函数
                    if (null != callback) {
                        callback.onInterrupt(postcard);
                    }
                }
            });
        } else {
            return _navigation(context, postcard, requestCode, callback);
        }

        return null;
    }

4.5、LogisticsCenter.completion

    public synchronized static void completion(Postcard postcard) {
        ...省略代码...
		//获取本次路由的元信息,这个信息是在routes文件夹下对应的类中 添加的
        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
        //如果没有元信息,说明还没有加载,就先把它所在的路由组 所包含的路由信息
        if (null == routeMeta) {    // Maybe its does't exist, or didn't load.
           //获取路由组 元信息
            Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup());  // Load route meta.
            if (null == groupMeta) {
                ...省略报错代码...
            } else {
                // Load route and cache it into memory, then delete from metas.
                try {
                    //获取路由组的实例
                    IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
                    //加载该路由组下面所有的路由
                    iGroupInstance.loadInto(Warehouse.routes);
                    //删除该路由组
                    Warehouse.groupsIndex.remove(postcard.getGroup());

                } catch (Exception e) {
                    throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
                }
				//再次调用该函数,这次调用就不会再走到这里了,因为它的路由组被加载后,该路由肯定不为空
                completion(postcard);   // Reload
            }
        } else {
            //设置当前路由的class
            postcard.setDestination(routeMeta.getDestination());
            //设置当前路由的类型,参考 RouteType枚举类
            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()) {
               //如果是provide类型的,就找到路由对应的class,进行实例化
                case PROVIDER:  // if the route is provider, should find its instance
                    // Its provider, so it must implement IProvider
                    //获取当前路由对应的class
                    Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
                    //尝试在Warehouse 中获取路由对应的provide 对象
                    IProvider instance = Warehouse.providers.get(providerMeta);
                    //获取不到,则通过反射创建新的provide对象
                    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) {
                            throw new HandlerException("Init provider failed! " + e.getMessage());
                        }
                    }
                    postcard.setProvider(instance);
                    // 这里为本次路由开启了,绿色通道,也就是不经过拦截器
                    postcard.greenChannel();    // Provider should skip all of interceptors
                    break;
                case FRAGMENT:
                    // 同上,只有这两个地方,是不经过拦截器
                    postcard.greenChannel();    // Fragment needn't interceptors
                default:
                    break;
            }
        }
    }

LogisticsCenter.completion 执行完,会继续回到4.5 _ARouter#navigation 执行

4.6、InterceptorServiceImpl#doInterceptions

还记得在 _ARouter.afterInit(); 吗,它自举了 路由 /arouter/service/interceptor,声明该路由的类就是InterceptorServiceImpl

    public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
        //Warehouse.interceptors 中的拦截器,是在初始化时register 函数中设置的
        if (null != Warehouse.interceptors && Warehouse.interceptors.size() > 0) {

            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 {
                        //执行拦截器,如果拦截器继续,则在内部继续调用_execute
                        _execute(0, interceptorCounter, postcard);
                       
                        interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
                        
                        if (interceptorCounter.getCount() > 0) {    // Cancel the navigation this time, if it hasn't return anythings.
                            callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
                        } else if (null != postcard.getTag()) {    // Maybe some exception in the tag.     
                           //在拦截器中断,可传递异常到postcard中
                            callback.onInterrupt(new HandlerException(postcard.getTag().toString()));
                        } else {
                            callback.onContinue(postcard);
                        }
                    } catch (Exception e) {
                        callback.onInterrupt(e);
                    }
                }
            });
        } else {
           //如果没有拦截器,则默认执行 interceptorService.doInterceptions 中拦截器的onContinue
            callback.onContinue(postcard);
        }
    }
    private static void _execute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
        if (index < Warehouse.interceptors.size()) {
            IInterceptor iInterceptor = Warehouse.interceptors.get(index);
            iInterceptor.process(postcard, new InterceptorCallback() {
                @Override
                public void onContinue(Postcard postcard) {
                    // Last interceptor excute over with no exception.
                    //执行完一个拦截器,拦截器计数器减一
                    counter.countDown();
                    //执行下一个拦截器
                    _execute(index + 1, counter, postcard);  // When counter is down, it will be execute continue ,but index bigger than interceptors size, then U know.
                }

                @Override
                public void onInterrupt(Throwable exception) {
                    // Last interceptor excute over with fatal exception.

                    postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage());    // save the exception message for backup.
                    counter.cancel();
                }
            });
        }
    }

执行完拦截器处理,代码回到 4.5、LogisticsCenter.completion

4.7、_ARouter#_navigation

真正处理路由的函数,是开启activity,还是返回provide的实例,还是开启fragment等


    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()) {
            case ACTIVITY:
               
                // Build intent
                final Intent intent = new Intent(currentContext, postcard.getDestination());
                 // 传入参数
                intent.putExtras(postcard.getExtras());

                // Set flags.
                int flags = postcard.getFlags();
                if (-1 != flags) {
                    intent.setFlags(flags);
                } else if (!(currentContext instanceof Activity)) {    // Non activity, need less one flag.
                    intent.setFlags(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:
                //provide实例 已经在LogisticsCenter.completion 中创建好了,这里直接返回
                return postcard.getProvider();
            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;
    }

至此,处理路由的主要流程就分析完成了,拦截器,provide等的路由处理,和上面类似。下面来看看,参数是如何传递到被启动的activity中的

4.7、ARouter##inject

在被启动的界面,需要使用 ARouter.getInstance().inject(this); 将传递过来的参数,自动注入到本类 使用了@Autowired 注解的变量中

下面就来看看inject 函数

    static void inject(Object thiz) {
        //通过路由获取/arouter/service/autowired  的实例,AutowiredServiceImpl,这个也是在arouter-api中实现的 
        AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
        if (null != autowiredService) {
            autowiredService.autowire(thiz);
        }
    }

到AutowiredServiceImpl类中,查看autowire 函数

    @Override
    public void autowire(Object instance) {
        //获取被启动类的实例
        String className = instance.getClass().getName();
        try {
             //检查是否在黑名单中
            if (!blackList.contains(className)) {
               //先尝试在缓存中获取,获取到的对象是,arouter-complier 对Autowired 注解处理 生成的类
                ISyringe autowiredHelper = classCache.get(className);
                if (null == autowiredHelper) {  // No cache.
                    autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
                }
                //调用该实例的inject ,例如 Test2Activity$$ARouter$$Autowired 中的inject
                autowiredHelper.inject(instance);
                //加入缓存
                classCache.put(className, autowiredHelper);
            }
        } catch (Exception ex) {
            //如果 注解发生异常,就把该类 加入黑名单
            blackList.add(className);    // This instance need not autowired.
        }
    }

下面来看看Test2Activity$$ARouter$$Autowired的具体实现

public class Test2Activity$$ARouter$$Autowired implements ISyringe {
  private SerializationService serializationService;

  @Override
  public void inject(Object target) {
    //通过by type的方式,获取一个可以处理json的对象
    serializationService = ARouter.getInstance().navigation(SerializationService.class);
    Test2Activity substitute = (Test2Activity)target;
    //为被启动类 的变量赋值,这样就实现了Ioc的功能
    substitute.key1 = substitute.getIntent().getExtras() == null ? substitute.key1 : substitute.getIntent().getExtras().getString("key1", substitute.key1);
  }
}

下面我们来看看,如何通过by type 来获取provide实例

4.7、ARouter## T navigation(Class<? extends T> service)

通过type的方式获取provide 是这样使用的ARouter.getInstance().navigation(SerializationService.class);
也是navigation 函数,可以看到传入参数不同

最终调用到_ARouter 的navigation中

    protected <T> T navigation(Class<? extends T> service) {
        try {
            //先在Warehouse.providersIndex 中获取对应类型的路由元数据
            //Warehouse.providersIndex的数据 初始化时在registerProvider 中添加的,
            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;
            }
           //路由的元数据,不为空,就去实例化对应的路由对象
            LogisticsCenter.completion(postcard);
            //最后返回provide对象
            return (T) postcard.getProvider();
        } catch (NoRouteFoundException ex) {
            logger.warning(Consts.TAG, ex.getMessage());
            return null;
        }
    }

关于arouter-register

通过字节码插桩的方式实现,如果不使用这个也是可以的,流程走的就是 4.1、初始化 时,LogisticsCenter init函数中的else 语句,它们的效果是一样的,只是加固可能会出现问题,

下面是官方的描述

可选使用,通过 ARouter 提供的注册插件进行路由表的自动加载(power by AutoRegister), 默认通过扫描 dex
的方式 进行加载通过 gradle 插件进行自动注册可以缩短初始化时间解决应用加固导致无法直接访问 dex
文件,初始化失败的问题,需要注意的是,该插件必须搭配 api 1.3.0 以上版本使用!

至此,ARouter的主要功能流程,就分析完了

©️2020 CSDN 皮肤主题: 撸撸猫 设计师:设计师小姐姐 返回首页