面试:ARouter原理

ARouter原理概述:

一、路由表生成:编译时注解加上注解处理器生成路由表

二、路由表加载:LogisticsCenter通过反射加载这些路由信息表。

ARouter 是阿里开源的一款帮助 Android APP 进行组件化改造的路由框架,可以实现在同一个项目中互不依赖的的模块的 Activity 之间跳转。

ARouter 的路由参数拦截器都是用注解来标注的。注解在 Retrofit、Dagger 和 EventBus 中都有使用。

ARouter 的跳转是基于路由表 RouterMap 实现的,

1、负责生成路由表的是 RouteProcessor ;

2、负责加载路由表的是 LogisticsCenterRegisterTransform

1、负责生成路由表的是 RouteProcessor ;

注解分为运行时注解编译时注解编译时注解是依赖注解处理工具 APT(Annotation Processing Tool)实现的,用于在编译时扫描和处理注解,通过 APT 我们能少写很多模板代码。在编译时,编译器会检查 AbstractProcessor 的子类,并调用 AbstractProcessor 的子类的 process() 方法,然后把添加了注解的元素都传到 process() 方法中,这样我们就可以在 process() 函数中生成新的 Java 类文件。

RouteProcessor 是一个注解处理器,是 AbstractProcessor 的子类。在 RouteProcessor 的 process() 方法中,会调用 parseRoutes() 方法,parseRoutes() 方法会用 JavaPoet API 来生成 Java 代码,具体的代码就是 Activity 等类的 Class 信息。除了 RouteProcessor ,ARouter 中还有参数注解处理器 AutowiredProcessor 和拦截器注解处理器 InterceptorProcessor ,它们的原理和 RouteProcessor 是一样的。

当我们调用 ARouter 的 build() 方法后,会获取到一个 Postcard 对象,我们调用的 navigation() 方法就是 Postcard 的 navigation() 方法,Postcard 的 navigation() 方法会调用到 _ARoute 的 navigation() 方法中,在这方法中,首先会处理预处理服务,然后会让 LogisticsCenter 填充 Postcard 中的信息,如果 LogisticsCenter 没有找到对应的路由信息的话,就会走降级策略的逻辑,如果 LogisticsCenter 找到对应的路由信息的话,就会判断是不是走绿色通道,如果不走绿色通道的话就由拦截器链决定要不要跳转。如果走绿色通道的话,就直接按 Fragment 和 Activity 等不同的类型进行跳转,在跳转完成后,如果设置了跳转回调, LogisticsCenter 就会调用这个回调。

预处理服务具体就是一个 PretreatmentService 接口,只要定义一个实现了这个接口的类,并给这个类加一个 @Route 注解就可以使用了,预处理服务的作用,是做一些跳转的时候,在加载路由表前的判断。

降级策略的作用是跳转路由的信息缺失的时候,要做的事情,比如说给用户弹一个错误提示或记录错误日志等,降级策略对应的是一个 DegradeService 接口,定义一个实现这个接口的类,并添加上 @Route 注解就可以使用降级策略了。

绿色通道的作用就是判断要不要走拦截器链,比如说我们定义了一个登陆拦截器,但是某个页面不需要做这个判断,就可以走绿色通道,走绿色通道只要在调用 build() 方法后调用 greenChannel() 方法就可以了。

拦截器具体就是一个添加了 @Interceptor 注解并实现了 IInterceptor 接口的类,通过拦截器我们能做一些类似登录态判断等逻辑。

跳转回调具体就是一个传到 navigation() 方法中的 NavigationCallback 接口或 NavCallback 抽象类。

2、负责加载路由表的是 LogisticsCenter

所谓的加载路由表,其实就是加载 RouteProcessor 生成的类文件

在我们调用 ARouter 的 init() 方法时,ARouter 会调用 LogisticsCenter 的 init() 方法,在 LogisticsCenter 的 init() 方法中,会判断当前路由表加载方式是否为插件,不是的话则从 Dex 中加载路由表,是的话则由插件从 Jar 中加载路由表

ARouter 加载路由表的方式有两种,一种是运行时反射,另一种是编译时插入

在 ARouter 的 init() 方法中会调用到 LogisticsCenter 的 init() 方法,LogisticsCenter 的 init() 方法会根据 registerByPlugin 的值判断路由表是否已经在编译时插入,如果不是的话,就通过运行时反射注册路由表的信息。

运行时反射就是在 LogisticsCenter 的 init() 方法中,通过 ClassUtils 加载 dex 文件中的 Class 信息,然后再通过反射初始化这些类,并保存到仓库 Warehouse 中。

Dex 文件是 Android 平台的可执行文件,类似于 Windows 中的 exec 文件,每个 APK 安装包中都有 dex 文件,dex 文件中包含了 app 的所有源码,反编译后能看到对应的 java 源码。

编译时插入就是由 RegisterTransformJar 文件中读取路由表的信息。 RegisterTransform 继承了 Transform 类,Transform 是 Android 官方提供的用来修改 class 等资源的 API ,每个 Transform 都是一个 Gradle 任务,能读取和处理 jar、aar 和 resource 等资源,用户自定义的 Transform 会插在 Transform 队列的最前面。

Transform API 可以做很多的事情,比如在所有的 class 文件中插桩,做 UI 、内存和网络方面的性能监控。还可以通过修改某个第三方库的 class 文件的内容调整它的逻辑。还可以在 Log 中插入当前代码行数,这样更容易定位问题。还可以对任何类进行动态代理。还可以实现打印出某个方法的入参和出参的代码。

探索 ARouter 原理 - 掘金

上一篇:Android组件化之ARouter的使用,android开发平台环境


下一篇:ARouter 在多 module 项目中实战