ARouter使用和原理解析
github:https://github.com/alibaba/ARouter
本文参考:https://github.com/Xiasm/EasyRouter/wiki
一:ARouter介绍
组件化逐渐成为热潮,组件化可以使业务逻辑高度解耦、模块分离,提高开发效率,更有利于多人协作并行开发。组件化中两个单向依赖的module之间互相启动对方的Activity,因为没有相互引用startActivity()是实现不了的,必须需要一个协定的通信方式,此时ARouter路由框架就派上用场了。ARouter是阿里巴巴开源路由框架,主要解决组件间、模块间的界面跳转问题。
二:ARouter基础功能使用
1):添加依赖和配置
java和kotlin配置不一样,本文以kotlin和gradle3.4+进行配置的。
在module中build.gradle配置
apply plugin: 'kotlin-kapt'
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
dependencies {
implementation 'com.alibaba:arouter-api:1.5.0'
kapt 'com.alibaba:arouter-compiler:1.2.2'
}
2)::在目标页面Activity添加注解
// 在支持路由的页面上添加注解(必选) // 这里的路径需要注意的是至少需要有两级,/xx/xx
@Route(path = "/test/activity")
public class YourActivity extend Activity { ... }
3):初始化SDK
/**
* 初始化ARouter
*/
private fun initARouter() {
if (BuildConfig.DEBUG) { //如果在debug模式下
// 打印日志,默认关闭
ARouter.openLog()
// 开启调试模式,默认关闭(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
ARouter.openDebug()
// 打印日志的时候打印线程堆栈
ARouter.printStackTrace()
}
// 尽可能早,推荐在Application中初始化
ARouter.init(this)
}
4.发起路由操作
// 1. 应用内简单的跳转(通过URL跳转在'进阶用法'中)
ARouter.getInstance().build("/test/activity").navigation();
// 2. 跳转并携带参数
ARouter.getInstance().build("/test/1") .withLong("key1", 666L)
.withString("key3", "888")
.withObject("key4", new Test("Jack", "Rose")) .navigation();
三:ARouter原理
1):@Route注解的作用
在需要对其他module提供调用的Activity中,都需要声明@Route注解,我们称之为路由地址。
@Route(path = "/userCenter/login")
class LoginActivity : AppCompatActivity(){...}
那么这个注解有什么用呢?
路由框架会在项目的编译期通过注解处理器扫描所有@Route注解的Activity类,然后将Route注解中的path地址和Activity.class文件的映射关系保存到它自己生成的java文件的map中。
伪代码:
public class MyRouters {
//项目编译后通过apt生成如下方法
public static HashMap getRouteInfo(HashMap routes) {
route.put("/userCenter/login", LoginActivity.class);
route.put("/userCenter/register”, RegisterActivity.class);
}
}
2):ARouter如何实现跳转
//用ARouter启动Activity,代码如下:
ARouter.getInstance().build("/userCenter/login").navigation();
//实现伪代码:
public void login(String name, String password) {
HashMap route = MyRouters.getRouteInfo(new HashMap);
LoginActivity.class classBean = route.get("/userCenter/login");
Intent intent = new Intent(this, classBean);
intent.putExtra("name", name);
intent.putExtra("password", password);
startActivity(intent);
}
总结:
1.代码编译期
路由框架在这个时期根据注解@Route去扫描所有文件,然后生成路由映射文件(path和activity.class)。这些文件都会统一打包到apk里。 apt生成的路由映射关系文件,在项目编译后会在各个模块的/build/generated/source/apt文件夹下面生成。
2.代码运行期:
使用路由跳转之前需要获取路由映射关系并保存到内存中。那么获取路由关系最好的时机就是应用程序初始化的时候,也就是我们的ARouter.init()方法;它会加载我们在编译时期生成的路由映射关系文件,获取映射关系保存到内存(map)中。
3.页面跳转
进行路由跳转的时候,通过build()方法传入目标页面的路由地址,ARouter会通过它自己存储的路由表找到路由地址对应的Activity.class(activity.class = map.get(path)),然后new Intent(context, activity.Class),当调用ARouter的withString()方法它的内部会调用intent.putExtra(String name, String value),调用navigation()方法,它的内部会调用startActivity(intent)进行跳转,这样便可以实现两个相互没有依赖的module顺利的启动对方的Activity了。
四:ARouter进阶用法
1):跳转界面不带参
2):跳转界面带参
3):跳转界面传递对象
4):Uri跳转
5):跳转结果监听
6):声明拦截器(拦截跳转过程,面向切面编程)
7):为目标页面声明更多信息
8):依赖注入解耦
补充:
Q1:组件化中模块之间的Activity跳转,为什么选择ARouter路由跳转
1):隐式跳转,但是一个项目中不可能所有的跳转都是隐式的,这样Manifest文件会有很多过滤配置,而且非常不利于后期维护。
2):反射拿到Activity的class文件也可以实现跳转,
缺点:1大量的使用反射跳转对性能会有影响,
2.需要拿到Activity的类文件,在组件开发的时候,想拿到其他module的类文件是很麻烦的,因为组件开发的时候组件module之间是没有相互引用的,你只能通过找到类的路径去反射拿到这个class。
Q2:什么是APT
APT是Annotation Processing Tool的简称,即注解处理工具。apt是在编译期对代码中指定的注解进行解析,然后做一些其他处理(如通过javapoet生成新的Java文件)。我们常用的ButterKnife,其原理就是通过注解处理器在编译期扫描代码中加入的@BindView、@OnClick等注解进行扫描处理,然后生成XXX_ViewBinding类,实现了view的绑定。