组件化项目存在各个模块之间耦合,通信麻烦的问题 ,,为了解决这个问题,阿里巴巴的开发者就搞出了Arouter这个框架,以解决上述问题.
Arouter 支持模块间的路由、通信、解耦
1.依赖和配置
1.1 Java 环境配置方案
android {
compileSdkVersion = 30
buildToolsVersion = "30.0.3"
defaultConfig {
applicationId "com.wu.material"
....
//ARouter 配置
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
dependencies {
implementation 'com.alibaba:arouter-api:1.5.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.2.1'
}
}
1.2 Kotlin 环境配置方案
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
android {
compileSdkVersion = 30
buildToolsVersion = "30.0.3"
defaultConfig {
applicationId "com.wu.material"
}
dependencies {
implementation 'com.alibaba:arouter-api:1.5.1'
kapt 'com.alibaba:arouter-compiler:1.2.1'
}
}
注意:
Kotlin 环境和 Java 环境配置不匹配会报错 ARouter::There is no route match the path
W/ARouter::: ARouter::There is no route match the path [/xxx/xxx], in group [xxx][ ]"
2. 在Application初始化
/**
* 初始化路由
*/
private fun initArouter() {
// 这两行必须写在init之前,否则这些配置在init过程中将无效
if (BuildConfig.DEBUG) {
// 打印日志
ARouter.openLog();
// 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
ARouter.openDebug();
}
ARouter.init(this)
}
override fun onTerminate() {
super.onTerminate()
//阿里router需要释放
ARouter.getInstance().destroy()
}
3.Arouter 使用
3.1 Activity Fragment路由配置以及调用
// 这里的路径需要注意的是至少需要有两级,/xx/xx
//注解
@Route(path = "/arouter/ArouterActivity")
class ArouterActivity:AppCompatActivity() {
...
//获取数据
var key2=getIntent().getStringExtra(key2")
}
// 跳转
ARouter.getInstance().build("/arouter/ArouterActivity")
.withLong("key1", 1l)
.withString("key2", "888")
.withObject("key3", new UserInfo("Jack", "Rose"))
.navigation();
额外方法:
// 构建标准的路由请求
ARouter.getInstance().build("/home/main").navigation();
// 构建标准的路由请求,并指定分组
ARouter.getInstance().build("/home/main", "ap").navigation();
// 构建标准的路由请求,通过Uri直接解析
Uri uri;
ARouter.getInstance().build(uri).navigation();
// 构建标准的路由请求,startActivityForResult
// navigation的第一个参数必须是Activity,第二个参数则是RequestCode
ARouter.getInstance().build("/home/main", "ap").navigation(this, 5);
// 直接传递Bundle
Bundle params = new Bundle();
ARouter.getInstance()
.build("/home/main")
.with(params)
.navigation();
// 指定Flag
ARouter.getInstance()
.build("/home/main")
.withFlags();
.navigation();
// 获取Fragment
Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
// 对象传递
ARouter.getInstance()
.withObject("key", new TestObj("Jack", "Rose"))
.navigation();
// 觉得接口不够多,可以直接拿出Bundle赋值
ARouter.getInstance()
.build("/home/main")
.getExtra();
// 转场动画(常规方式)
ARouter.getInstance()
.build("/test/activity2")
.withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
.navigation(this);
// 转场动画(API16+)
ActivityOptionsCompat compat = ActivityOptionsCompat.
makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);
// ps. makeSceneTransitionAnimation 使用共享元素的时候,需要在navigation方法中传入当前Activity
ARouter.getInstance()
.build("/test/activity2")
.withOptionsCompat(compat)
.navigation();
// 使用绿色通道(跳过所有的拦截器)
ARouter.getInstance().build("/home/main").greenChannel().navigation();
// 使用自己的日志工具打印日志
ARouter.setLogger();
// 使用自己提供的线程池
ARouter.setExecutor();
3.2 Arouter 路由跳转的拦截器 IInterceptor(拦截跳转过程,面向切面编程)
// 比较经典的应用就是在跳转过程中处理登陆事件,这样就不需要在目标页重复做登陆检查
// 拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行
@Interceptor(priority = 10, name = "测试拦截器")
class ArouterInterceptor : IInterceptor {
var mContext: Context? = null
// 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次
override fun init(context: Context?) {
mContext = context
}
override fun process(postcard: Postcard?, callback: InterceptorCallback?) {
Log.e("传递的数据", "")
if (postcard != null) {
var service = ARouter.getInstance().navigation(UserService::class.java)
//跳转过程中添加数据以及处理数据
postcard!!.extras.putString("uid", service.getUid())
}
if (callback != null) {
//传递到页面
callback!!.onContinue(postcard);
}
// 觉得有问题,中断路由流程
// callback.onInterrupt(new RuntimeException("我觉得有点异常"));
// 以上两种至少需要调用其中一种,否则不会继续路由
}
}
3.3 处理跳转结果
// 增加整个跳转过程的监听 ARouter.getInstance().build("/rv/MediaPlayerActivity").withString("name", "测试名字数据")
.navigation(mContext, object : NavigationCallback {
override fun onFound(postcard: Postcard?) {
Log.e("Arouter", "onFound")
}
override fun onLost(postcard: Postcard?) {
Log.e("Arouter", "onLost")
}
override fun onArrival(postcard: Postcard?) {
Log.e("Arouter", "onArrival")
}
override fun onInterrupt(postcard: Postcard?) {
Log.e("Arouter", "onInterrupt")
}
})
3.4 通过依赖注入解耦:服务管理
/**
* @author wkq
*
* @date 2022年05月17日 16:45
*
*@des 创建服务
*
*/
interface UserService:IProvider {
fun getUid():String?
fun getName():String?
fun getFace():String?
}
/**
* @author wkq
*
* @date 2022年05月17日 16:46
*
*@des 实现服务
*
*/
// 注解
@Route(path = "/service/UserSericice")
class UserServiceImpl:UserService {
override fun getUid(): String? {
return nickUid
}
override fun getName(): String? {
return nickName
}
override fun getFace(): String? {
return nickFace
}
var nickName=""
var nickFace=""
var nickUid=""
override fun init(context: Context?) {
nickName="我是测试"
nickFace="我是头像"
nickUid="10010"
}
}
//调用IProvider 获取数据
//方法1
var service = ARouter.getInstance().navigation(UserService::class.java)
var name= service.getName()
//方法2
var userServiceImpl =ARouter.getInstance().build("/service/UserSericice").navigation() as UserServiceImpl
var userName = userServiceImpl.getName()
总结
简单的调用了一下Arouter的一些方法,整体功能够用了,在模块化架构的时候Arouter是个利器,一些高级别使用方式没有一一列举,又兴趣的可以去官网看一下,地址放在结尾
欢迎点赞!!!