简单说就是映射页面跳转关系的一个中间件,其中包含有一些跳转时的辅助功能(参数传递、动画、拦截器、服务绑定、碎片对象获取等)。
ARouter内部使用了注解处理工具APT(Annotation Processing Tool )技术,在代码编译期间对注解进行处理,生成JAVA文件,形成映射关系类。_ARouter中的init方法内,通过系统ClassUtils寻找到‘com.alibaba.android.arouter.routes’相关的类集合然后添加到一个IProviderGroup中的一个代理Map集合(key是path,value是RouteMeta参数体)中完成所有的初始化工作,具体生成的文件在 build/generated/source/kapt/下可以看到;在执行跳转时通过ARouter的build接收path,navigation接收配置的跳转模式设置,最终根据path找到对应的RouteMeta里的destination,也就是className,利用系统的startActivity/startActivityForResult完成跳转.
- 跨模块跳转,模块间解耦;
- 拦截跳转过程,开发者可控;
- 统一处理了跳转时各种参数和目标类检索出现的异常;
- 可从外部URL映射到内部页面(js/html等与本地直接交互和界面切换);
- 通过给任意一个类(fragment、boardcast、content_provider、object、any等)添加注解,都可以获取到该实例;
- 通过给变量配置Autowired注解,可以自动获取并解析外界传进来的参数(配合
ARouter.getInstance().inject(this)
使用)
- 每个需要跳转或者构造的类都需要添加注解;
- 当在使用从外部URL映射到内部页面时存在安全风险;
- 增加项目编译时长.
- 暂时无法跳转到系统界面(不能设置intent的type、action、data等属性,这是由于Arouter依赖注解所决定的)
- 在遇到有回调的跳转(startActivityForResult)时,requestCode必须大于0,不能设置0或者小于0的值(_ARouter类中的_navigation方法在判断时根据requestCode > 0选择跳转的模式)
Kotlin 或 Kotlin与Java混编的模式项目
apply plugin: 'kotlin-kapt'
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
...
dependencies {
...
implementation 'com.alibaba:arouter-api:x.x.x'
kapt 'com.alibaba:arouter-compiler:x.x.x'
}
Java模式项目
android {
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
}
dependencies {
// 替换成最新版本, 需要注意的是api
// 要与compiler匹配使用,均使用最新版可以保证兼容
implementation 'com.alibaba:arouter-api:x.x.x'
annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
...
}
属性);6.1、初始化SDK
// 这两行必须写在init之前,否则这些配置在init过程中将无效
if (isDebug()) {
// 打印日志
ARouter.openLog();
// 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
ARouter.openDebug();
}
// 建议在Application中初始化
ARouter.init(mApplication);
6.2、基本用法
// 1. 应用内简单的跳转(通过URL跳转在'进阶用法'中)
ARouter.getInstance().build("/test/activity").navigation();
// 2. 应用内携带参数跳转
ARouter.getInstance().build("/test/activity")
.withLong("key1", 666L)
.withString("key3", "888")
.withObject("key4", new Test("Hxd", "hxjr"))
.navigation();
//3. 跳转结果监听
ARouter.getInstance().build("/test/activity").navigation(this, object : NavCallback() {
override fun onFound(postcard: Postcard?) {
ToastUtils.showText(this@MainActivity, "界面找到了,分组是${postcard?.group}")
}
override fun onLost(postcard: Postcard?) {
Log.d("ARouter", "找不到了")
}
override fun onArrival(postcard: Postcard) {
Log.d("ARouter", "跳转完了")
}
override fun onInterrupt(postcard: Postcard?) {
Log.d("ARouter", "被拦截了")
}
})
//4 .自定义路由分组 (默认每个路径的第一级就是该路径的分组,这里可以动态指定和修改(目标界面里注解))
ARouter.getInstance().build(path2TestActivity, "main").navigation(this, object : NavCallback() {
override fun onArrival(postcard: Postcard) {
ToastUtils.showText(this@MainActivity, "跳转完了,分组是${postcard.group}")
}
//5.跳转回调
ARouter.getInstance().build(path2ForResultActivity).navigation(this, 1)
//6. 跳转时跳过所有的拦截器
ARouter.getInstance().build(path2InterceptorTestActivity).greenChannel().navigation()
//7.增加转场动画
ARouter.getInstance().build(path2InterceptorTestActivity) .withOptionsCompat(
ActivityOptionsCompat.makeCustomAnimation(
this,
R.anim.slide_in_bottom, R.anim.slide_out_bottom
)
).navigation()
//8.设置跳转的flags
ARouter.getInstance().build(path2InterceptorTestActivity).withFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).navigation()
//9.获取Fragment
val fragment = ARouter.getInstance().build(path2TestFragment).navigation() as Fragment
//添加Fragment
supportFragmentManager.beginTransaction().run {
add(R.id.fragmentLayout, fragment)
commit()
}
//10、 使用自己的日志工具打印日志
ARouter.setLogger();
//11、 使用自己提供的线程池
ARouter.setExecutor();
6.3、跳转时添加拦截器
/**
* @Function 自定义拦截器 (定义完成后不需要手动调用该对象,在执行跳转时只要不调用ARouter的greenChannel()方法,默认都会走该拦截器)
*
* 比较经典的应用就是在跳转过程中处理登陆事件,这样就不需要在目标页重复做登陆检查
* 其次是在获取或构造某个对象时,可以统一对属性值进行修改
*
* 拦截器会在跳转之间执行,多个拦截器会按优先级(priority)顺序依次执行(值越小级别越高)
*
* 拦截器是在线程里执行的,为了逻辑的处理不阻塞主线程
*/
@Interceptor(priority = 1, name = "登陆测试用拦截器")
class CustomLoginInterceptor : IInterceptor {
override fun process(postcard: Postcard?, callback: InterceptorCallback?) {
//只对指定的界面做处理,这里也可以判断分组
if (postcard?.path == "/test/interceptor") {
try {
val text = "拦截到了InterceptorTestActivity的跳转\n优先级别是:${postcard.priority}\n已登陆"
MainActivity.getThis.activity?.runOnUiThread {
ToastUtils.showText(MainActivity.getThis.activity!!, text)
}
// 处理完成,交还控制权
callback?.onContinue(postcard)
} catch (e: Exception) {
e.toString()
// 觉得有问题,中断路由流程
callback?.onInterrupt(RuntimeException("我觉得有点异常"));
}
} else
callback?.onContinue(postcard)
}
override fun init(context: Context?) {
// 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次
}
}
6.4、与Html / JS等外部Uri互调
6.4.1
//先在本地WebView中或者设备自带的浏览器加载对应的网页
webView.loadUrl("file:///android_asset/schame-test.html")
//注意网页里的跳转链接写法(arouter是scheme,hxd是host,。可以根据自己需要定义和命名):
arouter://hxd/test/uri
6.4.2
/**
* 1、先在本地WebView中或者设备自带的浏览器加载对应的网页
*/
webView.loadUrl("file:///android_asset/schame-test.html")
/**
* 2、接着定义一个接受外部网页回调的中转Activity
*/
public class URLReceiveActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//对URI 数据分发
Uri uri = getIntent().getData();
ARouter.getInstance().build(uri).navigation();
finish();
}
}
// 中转Activity在manifest中的注册 (这里的host和scheme要和网页里的链接保持一致)
/**
* 3、URL Activity
*/
@Route(path = "/test/uri")
public class URLActivity1 extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_url);
}
}
6.5、重写跳转URL路径
/**
*
* @Function 在没有或过滤掉拦截器的情况下实现跳转时路径重定向、保存跳转的历史数据等功能(定义完成后不需要手动调用该对象,在执行跳转时默认都会走该服务类))
*
* 这里的注解路径随便定义,只要不为空就行
*/
@Route(path = "/xxx/xxx")
class PathReplaceServiceImpl : PathReplaceService {
override fun forString(path: String): String {
//按照一定的规则处理之后返回处理后的结果
// TODO
return path
}
override fun forUri(uri: Uri): Uri {
// 按照一定的规则处理之后返回处理后的结果
return uri
}
override fun init(context: Context?) {
}
}
6.6、生成路由文档
// 更新 build.gradle, 添加参数 AROUTER_GENERATE_DOC = enable
// 生成的文档路径 : build/generated/source/apt/(debug or release)/com/alibaba/android/arouter/docs/arouter-map-of-${moduleName}.json
android {
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName(), AROUTER_GENERATE_DOC: "enable"]
}
}
}
}
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep public class com.alibaba.android.arouter.facade.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}
# 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
-keep interface * implements com.alibaba.android.arouter.facade.template.IProvider
# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
# -keep class * implements com.alibaba.android.arouter.facade.template.IProvider
Demo地址:https://github.com/yinzhengwei/ArouterDemo
ARouter地址:https://github.com/alibaba/ARouter