一、路由表生成:编译时注解加上注解处理器生成路由表
二、路由表加载:LogisticsCenter通过反射加载这些路由信息表。
ARouter 是阿里开源的一款帮助 Android APP 进行组件化改造的路由框架,可以实现在同一个项目中互不依赖的的模块的 Activity 之间跳转。
ARouter 的路由、参数和拦截器都是用注解来标注的。注解在 Retrofit、Dagger 和 EventBus 中都有使用。
ARouter 的跳转是基于路由表 RouterMap 实现的,
1、负责生成路由表的是 RouteProcessor ;
2、负责加载路由表的是 LogisticsCenter 或 RegisterTransform 。
生成路由表的是 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 抽象类。
加载路由表的是 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 源码。
编译时插入就是由 RegisterTransform 从 Jar 文件中读取路由表的信息。 RegisterTransform 继承了 Transform 类,Transform 是 Android 官方提供的用来修改 class 等资源的 API ,每个 Transform 都是一个 Gradle 任务,能读取和处理 jar、aar 和 resource 等资源,用户自定义的 Transform 会插在 Transform 队列的最前面。
Transform API 可以做很多的事情,比如在所有的 class 文件中插桩,做 UI 、内存和网络方面的性能监控。还可以通过修改某个第三方库的 class 文件的内容调整它的逻辑。还可以在 Log 中插入当前代码行数,这样更容易定位问题。还可以对任何类进行动态代理。还可以实现打印出某个方法的入参和出参的代码。
探索 ARouter 原理 - 掘金
ARouter拦截器原理当我们调用 Postcard 的 navigation() 方法时,Postcard 会调用 _ARouter 的 navigation() 方法,然后 _ARouter 才会去加载路由表,下面看下 navigation() 的处理流程。
navigation() 方法就会加载路由表,把 RouteMeta 的信息填充到 Postcard 中,比如终点 destination 等信息,这个操作是由物流中心 LogisticsCenter 做的。
假如 LogisticsCenter 在完善明信片的过程中遇到了异常,比如找不到路径对应的目标,那么就会调用降级策略,我们可以在降级策略中显示错误提示等信息。
在明信片完善信息后,navigation() 就会把跳转事件交给拦截器链处理;
在拦截器链处理完成,并且没有中断跳转时,navigation() 就会按照路径类型跳转到不同的页面或调用自定义服务;
拦截器拦截器可以用来在跳转过程中处理事件,比如做登陆检查,拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行。
