Skip to content

导航流程

导航子系统遵循“事件驱动”的单向数据流:ViewModel 发起导航请求 → AppNavigator 发布事件 → AppNavHost 消费事件并驱动 NavController。这样既能解耦 ViewModel 与 UI,又方便在任意位置统一收敛动画、拦截逻辑。

1. ViewModel 发起请求

所有业务 ViewModel 都继承自 BaseViewModel(或其网络子类)。只要注入 AppNavigatorUserState,即可直接调用:

kotlin
@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

kotlin
suspend fun navigateTo(route: Any, navOptions: NavOptions? = null) {
    _navigationEvents.emit(NavigationEvent.NavigateTo(route, navOptions))
}

还有 navigateBack()navigateBackTo()popBackStackWithResult() 等同理。由于使用 SharedFlow,事件具备“冷启动”能力,UI 组件只需在组合时订阅即可。

3. AppNavHost 消费事件

AppNavHost 创建 NavController 后,借助 LaunchedEffect 持续收集事件,并调用扩展函数执行真正的导航:

kotlin
LaunchedEffect(navController) {
    navigator.navigationEvents.collectLatest { event ->
        navController.handleNavigationEvent(event)
    }
}

handleNavigationEvent 会根据事件类型调用 NavController.navigate()popBackStack()、或写入 SavedStateHandle(结果回传)。

4. NavHost 配置与动画

AppNavHost 内部通过 NavHost(...) 定义全局导航图:

  • startDestination = MainRoutes.Main
  • enterTransition / exitTransition / popEnterTransition / popExitTransition 统一配置左右滑动动画。
  • 依次挂载 mainGraphauthGraphuserGraph 等 Feature Graph。

如需扩展其他模块,只需在 NavHost builder 中调用对应的 Graph 函数。

总结

ViewModel(navigate) --> AppNavigator.SharedFlow --> AppNavHost.collect --> NavController

所有导航请求都沿着这条链路流动,任何环节的修改(例如统一动画、拦截逻辑、结果传递格式)都集中在 navigation 模块内完成,Feature 层无需关心实现细节。