路由配置
介绍
路由配置的目标是让每个模块独立维护页面入口,并由应用统一挂载。核心步骤是:
- 定义模块路由(
*Routes)。 - 提供模块跳转封装(
*Navigator)。 - 在 Feature 的
*Graph中注册页面。 - 在
AppNavHost中按模块组装 Graph。
步骤一:定义路由
路由统一放在 app/src/main/java/com/joker/kit/core/navigation/<module>/,并实现 NavKey。
kotlin
object DemoRoutes {
@Serializable
data object NetworkDemo : NavKey
@Serializable
data class NavigationWithArgs(
val goodsId: Long,
) : NavKey
}说明:
- 无参页面使用
data object。 - 带参页面使用
data class。 - 参数字段要语义化,避免使用不清晰命名。
步骤二:封装模块 Navigator(推荐)
在同模块新增 *Navigator.kt,统一对外暴露跳转方法:
kotlin
object DemoNavigator {
fun toNetworkDemo() {
navigate(DemoRoutes.NetworkDemo)
}
fun toNavigationWithArgs(goodsId: Long = 0) {
navigate(DemoRoutes.NavigationWithArgs(goodsId = goodsId))
}
}这样业务层无需感知路由细节,也不会在多个页面重复写同样的跳转代码。
步骤三:注册模块 Graph
各 Feature 模块在 feature/<module>/navigation 提供 *Graph.kt:
kotlin
fun EntryProviderScope<NavKey>.demoGraph() {
entry<DemoRoutes.NetworkDemo> {
NetworkDemoRoute()
}
entry<DemoRoutes.NavigationWithArgs> { key ->
NavigationWithArgsRoute(navKey = key)
}
}说明:
- 使用
entry<Route>()进行类型安全注册。 - 带参路由可以在
entrylambda 中直接拿到key。 - Route 层负责把参数传给 ViewModel,不建议直接在 UI 层处理业务参数。
步骤四:在 AppNavHost 统一组装
AppNavHost.kt 中通过 entryProvider 聚合模块 Graph:
kotlin
private fun appEntryProvider() = entryProvider {
mainGraph()
demoGraph()
authGraph()
userGraph()
}新增业务模块时,只需要新增自己的 *Routes、*Navigator、*Graph,再在这里挂一行即可。
参数传递到 ViewModel 的推荐写法
对于带参页面,建议在 Route 层把参数传入 ViewModel:
kotlin
@Composable
internal fun NavigationWithArgsRoute(
navKey: DemoRoutes.NavigationWithArgs,
viewModel: NavigationWithArgsViewModel = hiltViewModel<
NavigationWithArgsViewModel,
NavigationWithArgsViewModel.Factory
>(creationCallback = { factory -> factory.create(navKey) })
) {
NavigationWithArgsScreen(goodsId = viewModel.goodsId)
}这种方式可以保证“参数用于请求数据”的场景在 ViewModel 层完成,UI 只负责展示状态。
扩展示例(新增 Goods 模块)
core/navigation/goods/GoodsRoutes.kt定义路由。core/navigation/goods/GoodsNavigator.kt封装跳转方法。feature/goods/navigation/GoodsGraph.kt注册entry<GoodsRoutes.*>。AppNavHost.appEntryProvider()增加goodsGraph()。
小结
路由层保持三个原则:
- 路由声明集中(
*Routes)。 - 跳转入口集中(
*Navigator+ 简写函数)。 - 页面注册集中(
*Graph)。
这样在多模块场景下,结构清晰、边界明确、可维护性更高。