ARouter原理概述:
一、路由表生成:编译时注解加上注解处理器生成路由表
二、路由表加载:LogisticsCenter通过反射加载这些路由信息表。
ARouter 是阿里开源的一款帮助 Android APP 进行组件化改造的路由框架,可以实现在同一个项目中互不依赖的的模块的 Activity 之间跳转。
ARouter 的路由
、参数
和拦截器
都是用注解来标注的。注解在 Retrofit、Dagger 和 EventBus 中都有使用。
ARouter 的跳转是基于路由表
RouterMap
实现的,1、负责
生成路由表
的是RouteProcessor
;2、负责
加载路由表
的是LogisticsCenter
或RegisterTransform
。
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 源码。
编译时插入
就是由 RegisterTransform
从 Jar
文件中读取路由表的信息。 RegisterTransform 继承了 Transform
类,Transform 是 Android 官方提供的用来修改 class 等资源的 API
,每个 Transform 都是一个 Gradle
任务,能读取和处理 jar、aar 和 resource 等资源,用户自定义的 Transform 会插在 Transform 队列的最前面。
Transform API
可以做很多的事情,比如在所有的 class 文件中插桩,做 UI 、内存和网络方面的性能监控。还可以通过修改某个第三方库的 class 文件的内容调整它的逻辑。还可以在 Log 中插入当前代码行数,这样更容易定位问题。还可以对任何类进行动态代理。还可以实现打印出某个方法的入参和出参的代码。