导航流程
导航子系统遵循“事件驱动”的单向数据流:ViewModel 发起导航请求 → AppNavigator 发布事件 → AppNavHost 消费事件并驱动 NavController。这样既能解耦 ViewModel 与 UI,又方便在任意位置统一收敛动画、拦截逻辑。
1. ViewModel 发起请求
所有业务 ViewModel 都继承自 BaseViewModel(或其网络子类)。只要注入 AppNavigator、UserState,即可直接调用:
@HiltViewModel
class MainViewModel @Inject constructor(
navigator: AppNavigator,
userState: UserState
) : BaseViewModel(navigator, userState) {
fun openProfile() {
navigate(UserRoutes.Info) // 推新页
}
fun backToHome() {
navigateBackTo(MainRoutes.Main) // 回退到任意页面
}
}BaseViewModel 内部会先执行登录拦截(见 guard.md)再调用 AppNavigator。
2. AppNavigator 发布事件
AppNavigator 将各种操作封装为 NavigationEvent 并写入 MutableSharedFlow:
suspend fun navigateTo(route: Any, navOptions: NavOptions? = null) {
_navigationEvents.emit(NavigationEvent.NavigateTo(route, navOptions))
}还有 navigateBack()、navigateBackTo()、popBackStackWithResult() 等同理。由于使用 SharedFlow,事件具备“冷启动”能力,UI 组件只需在组合时订阅即可。
3. AppNavHost 消费事件
AppNavHost 创建 NavController 后,借助 LaunchedEffect 持续收集事件,并调用扩展函数执行真正的导航:
LaunchedEffect(navController) {
navigator.navigationEvents.collectLatest { event ->
navController.handleNavigationEvent(event)
}
}handleNavigationEvent 会根据事件类型调用 NavController.navigate()、popBackStack()、或写入 SavedStateHandle(结果回传)。
4. NavHost 配置与动画
AppNavHost 内部通过 NavHost(...) 定义全局导航图:
startDestination = MainRoutes.MainenterTransition/exitTransition/popEnterTransition/popExitTransition统一配置左右滑动动画。- 依次挂载
mainGraph、authGraph、userGraph等 Feature Graph。
如需扩展其他模块,只需在 NavHost builder 中调用对应的 Graph 函数。
总结
ViewModel(navigate) --> AppNavigator.SharedFlow --> AppNavHost.collect --> NavController所有导航请求都沿着这条链路流动,任何环节的修改(例如统一动画、拦截逻辑、结果传递格式)都集中在 navigation 模块内完成,Feature 层无需关心实现细节。