一、基础使用(必须会)
一个用于 Android 组件化开发的路由框架,主要解决:
- 跨组件跳转
- 组件间通信
- 解耦
简单说,就是统一管理所有页面跳转,让组件之间可以互相调用。
1. 添加依赖
项目级 build.gradle
gradle
arduino
buildscript {
dependencies {
classpath "com.alibaba:arouter-register:1.0.2"
}
}
模块级 build.gradle
gradle
javascript
plugins {
// 必须添加,用于注解处理器
id 'kotlin-kapt'
}
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
// 必须配置,用于区分不同模块
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
}
dependencies {
// ARouter 核心库
implementation 'com.alibaba:arouter-api:1.5.2'
// 注解处理器,用于生成路由表
kapt 'com.alibaba:arouter-compiler:1.5.2'
}
2. 初始化
在 Application 的 onCreate 中:
kotlin
scss
if (BuildConfig.DEBUG) {
ARouter.openLog()
ARouter.openDebug()
}
// 初始化 ARouter
ARouter.init(this)
2.1 核心注解详解
@Route 注解
用于标记可路由的页面、服务等。
kotlin
ini
@Route(
path = "/video/video_fragment", // 必须,唯一标识
group = "video", // 可选,分组,默认为path的第一个/后的部分
name = "视频页面", // 可选,描述
extras = Consts.USER_LOGIN // 可选,用于拦截器判断
)
class VideoFragment : Fragment() { ... }
3. 页面跳转
3.1 基础跳转
目标页面添加注解:
kotlin
kotlin
@Route(path = "/video/video_fragment")
class VideoFragment : Fragment() { ... }
发起跳转:
kotlin
scss
ARouter.getInstance()
.build("/video/video_fragment")// 目标路径
.navigation()// 执行跳转
3.2 带参数跳转
kotlin
vbscript
ARouter.getInstance()
.build("/video/video_fragment")
.withInt("id", 123)
.withString("name", "张三")
.withParcelable("user", User())// 自定义对象必须实现 Parcelable
.navigation()
3.3 接收参数
kotlin
kotlin
@Route(path = "/video/video_fragment")
class VideoFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val id = arguments?.getInt("id")
val name = arguments?.getString("name")
}
}
4. 结果返回
kotlin
kotlin
ARouter.getInstance()
.build("/video/video_fragment")
.navigation(this, 100) // 100是requestCode
// 在 onActivityResult 中接收
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 100 && resultCode == Activity.RESULT_OK) {
// 处理结果
}
}
5. 带回调的跳转
kotlin
kotlin
ARouter.getInstance()
.build("/video/video_fragment")
.navigation(this, object : NavigationCallback {
override fun onFound(postcard: Postcard?) {
// 找到了路由
}
override fun onLost(postcard: Postcard?) {
// 找不到路由
}
override fun onArrival(postcard: Postcard?) {
// 跳转成功
}
override fun onInterrupt(postcard: Postcard?) {
// 被拦截器中断
}
})
二、参数传递详解
1. 基本数据类型
kotlin
vbscript
.withInt("id", 123)
.withLong("time", System.currentTimeMillis())
.withString("name", "张三")
.withBoolean("isVip", true)
.withFloat("score", 95.5f)
.withDouble("price", 199.99)
2. 数组和集合
kotlin
less
.withIntArray("ids", intArrayOf(1, 2, 3))
.withStringArray("names", arrayOf("张三", "李四"))
.withStringArrayList("list", arrayListOf("a", "b", "c"))
3. 自定义对象
必须实现 Parcelable 接口:
kotlin
less
@Parcelize
data class User(val id: Int, val name: String) : Parcelable
// 传递
.withParcelable("user", User(1, "张三"))
.withParcelableArrayList("users", arrayListOf(User(1, "张三"), User(2, "李四")))
三、高级功能(进阶必备)
1. 拦截器(Interceptor)
用于统一处理跳转前的逻辑,比如登录拦截。
定义拦截器:
kotlin
kotlin
@Interceptor(
priority = 8, // 优先级,数字越小优先级越高
name = "登录拦截器" // 描述
)
class LoginInterceptor : IInterceptor {
override fun process(postcard: Postcard, callback: InterceptorCallback) {
// 获取目标页面的 extras
val extras = postcard.extras
// 判断是否需要登录
if (extras and Consts.USER_LOGIN != 0) {
if (isLogin()) {
// 已登录,继续跳转
callback.onContinue(postcard)
} else {
// 未登录,跳转到登录页
ARouter.getInstance().build("/user/login").navigation()
// 中断当前跳转
callback.onInterrupt(null)
}
} else {
// 不需要登录,继续跳转
callback.onContinue(postcard)
}
}
override fun init(context: Context?) {
// 初始化工作
}
}
使用拦截器:在目标页面的注解中添加拦截器:
kotlin
kotlin
@Route(path = "/video/video_fragment", extras = Consts.USER_LOGIN)
class VideoFragment : Fragment() { ... }
2. 降级策略(DegradeService)
当路由找不到时的处理逻辑。
实现降级服务:
kotlin
kotlin
@Route(path = "/degrade/service")
class DegradeServiceImpl : DegradeService {
override fun onLost(context: Context?, postcard: Postcard?) {
// 路由找不到时的处理,比如跳转到错误页
Toast.makeText(context, "页面不存在", Toast.LENGTH_SHORT).show()
}
}
3. PathReplaceService(路径替换)
kotlin
kotlin
@Route(path = "/replace/service")
class PathReplaceServiceImpl : PathReplaceService {
override fun forString(path: String): String {
// 替换路径,比如兼容旧版本路径
return if (path == "/old/video") "/video/video_fragment" else path
}
override fun forUri(uri: Uri): Uri {
return uri
}
}
4. 依赖注入(Autowired)
自动注入参数,无需手动 getIntent() 或 getArguments()。
目标页面:
kotlin
less
@Route(path = "/video/video_fragment")
class VideoFragment : Fragment() {
@Autowired(name = "id") // name 对应传递的 key
@JvmField // 必须添加,否则会报错
var userId: Int = 0
@Autowired // 如果变量名和 key 一致,可以省略 name
@JvmField
var userName: String? = null
@Autowired(required = false) // 非必须参数
@JvmField
var isVip: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ARouter.getInstance().inject(this) // 必须调用,否则注入失败
}
}
发起跳转:
kotlin
vbscript
ARouter.getInstance()
.build("/video/video_fragment")
.withInt("id", 123)
.withInt("isVip", true)
.withString("userName", "张三")
.navigation()
5. Fragment 跳转
kotlin
scss
val fragment = ARouter.getInstance().build("/video/video_fragment").navigation() as Fragment
supportFragmentManager.beginTransaction()
.replace(R.id.container, fragment)
.commit()
6. URI 跳转
xml
ini
<activity
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="myapp.com"
android:path="/video"
android:scheme="app" />
</intent-filter>
</activity>
跳转:
kotlin
scss
val uri = Uri.parse("app://myapp.com/video?id=123&name=张三")
ARouter.getInstance().build(uri).navigation()
四、总结
| 功能 | 用法 | 优点 |
|---|---|---|
| 基础跳转 | build(path).navigation() |
简单、统一 |
| 参数传递 | withXXX() |
类型安全 |
| 结果返回 | navigation(context, requestCode) |
标准 |
| 拦截器 | @Interceptor |
统一处理登录、权限等 |
| 降级策略 | DegradeService |
优雅处理路由丢失 |
| 依赖注入 | @Autowired |
自动注入参数,减少模板代码 |