Navigation Compose:什么是、架构及开发中的工作原理

作者: IT Sectr 发布日期: 2026-06-29 阅读时间: 8 分钟

Navigation Compose — 是一个 Jetpack 库,用于在基于 Jetpack Compose 构建的 Android 应用程序中进行声明式导航。与 FragmentManager 或基于 Intent 的导航不同,Navigation Compose 提供了通过 NavControllerNavHost 管理的统一路由图。根据 Google I/O (2025) 的数据,Navigation Compose 是 Compose 应用程序推荐的导航方式,被超过 70% 的新项目使用。该库支持传递类型化参数、深层链接、过渡动画以及通过 SavedStateHandle 与 ViewModel 集成。

要点

  • Navigation Compose — 用于在 Compose 中进行声明式导航的 Jetpack 库,具有统一的路由图
  • NavController — 管理导航栈和返回栈状态的中央控制器
  • NavHost — 通过带有路由的 composable 函数定义路由图的容器
  • 参数通过 NavType 和 SavedStateHandle 传递,支持类型化参数
  • 深层链接 — 通过外部 URL 进行导航,自动从 URI 解析参数

什么是 Navigation Compose?

Navigation Compose — 是 Jetpack 套件中的一个库,为 Compose 应用程序提供导航框架。该库基于与 View 系统的 Navigation Component 相同的原理,但适用于 Compose 的声明式特性:使用 composable 函数代替 FragmentTransaction,导航图通过 Kotlin DSL 构建。

Navigation Compose 与经典导航的关键区别 — 没有 FragmentManager。每个屏幕都是一个 composable 函数,在路由匹配时在 NavHost 中渲染。返回栈存储的不是 Fragment,而是包含路由、参数和状态的记录。这简化了架构,并消除了 Fragment 导航特有的生命周期冲突。

根据 Google (2025) 的数据,Navigation Compose 已从 experimental 演进到 stable,并从 2.8.0 版本开始成为 Jetpack 的一部分。该库支持 Material3、Type-Safe Navigation(通过 Kotlin Serialization)、嵌套图和模块化。唯一的限制 — 该库不支持 BottomNavigation 的 multi-back stack(无需手动配置),尽管 Google 正在努力解决这个问题。

Navigation Compose 的架构围绕三个实体构建:NavController(栈管理)、NavHost(图容器)和 NavDestination(带有 composable 的单独路由)。它们之间的交互是声明式的:开发者描述路由和参数,库处理加载、保存和恢复状态。

NavController — Navigation Compose 的核心元素,管理导航栈。通过 rememberNavController() 创建并传递给 NavHost。NavController 存储返回栈、当前入口点,并支持延迟操作(在图初始化后的深层链接)。

kotlin
@Composable
fun AppNavigation() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = "home") {
        composable("home") { HomeScreen(navController) }
        composable("profile/{userId}") { backStackEntry ->
            ProfileScreen(
                userId = backStackEntry.arguments?.getString("userId") ?: ""
            )
        }
    }
}

NavController 的主要方法:navigate(route) — 导航到路由,popBackStack() — 返回上一个屏幕,navigateAndClear(route) — 导航并清除栈。NavOptions 定义行为:launchSingleTop 防止重复,popUpTo 清除栈到指定路由,restoreState 恢复先前状态。

要从深层嵌套的 composable 函数访问 NavController,请通过 CompositionLocal 使用 NavHostController。LocalNavController 在 NavHost 内的 ScopedNavController 中提供。在 NavHost 之外(例如,在 BottomNavigation 中),控制器通过参数或 ViewModel 传递。

NavHost — 是一个 composable 容器,将 NavController 与路由图连接起来。每个路由通过 composable(route, arguments, deepLinks) 声明,其中 route 是带有可选 {param} 占位符的路由字符串。当当前路由与 route 匹配时,NavHost 渲染相应的 composable 块。

路由图是分层构建的:可以通过 navigation() 嵌套图来对模块内的路由进行分组。嵌套图有自己的 startDestination,并在公共路由前缀下合并。这允许组织模块化架构,每个功能模块注册自己的子图。

kotlin
NavHost(
    navController = navController,
    startDestination = "main"
) {
    composable("main") { MainScreen(navController) }
    navigation(
        route = "auth",
        startDestination = "auth/login"
    ) {
        composable("auth/login") { LoginScreen(navController) }
        composable("auth/register") { RegisterScreen(navController) }
    }
}

NavHost 通过 LocalBackDispatcher 自动处理系统返回按钮(back press)。在 Material3 Scaffold 中,默认获取 NavController 以确保 BottomNavigation 正常工作。NavHost 在路由更改时重新创建 composable,但通过 rememberSaveable 保留输入字段和滚动的状态。

在屏幕之间传递参数

Navigation Compose 支持通过路由参数和 NavType 在屏幕之间传递类型化参数。参数在路由中定义为 {paramName},并通过 composable() 中的 arguments 指定类型。NavType 支持 String、Int、Long、Float、Boolean、Parcelable 和 Serializable。

参数类型NavType路由示例
StringNavType.StringType"profile/{name}"
IntNavType.IntType"item/{id}"
BooleanNavType.BoolType"settings?enabled={flag}"
ParcelableNavType.ParcelableType"details/{item}"
FloatNavType.FloatType"map?lat={lat}&lng={lng}"

参数从 NavBackStackEntry 通过 arguments?.getType(key) 提取。对于必需参数使用 defaultValue,对于可选参数使用 nullable。Parcelable 支持仅适用于 Kotlin Parcelize 或 kotlinx.parcelize 库。对于复杂对象,建议传递 ID 并通过 ViewModel 加载数据,而不是序列化整个对象。

从 Navigation 2.8.0 版本开始,Type-Safe Navigation 与 Kotlin Serialization 一起可用:路由定义为数据类,参数定义为字段。这用类型化对象替换了字符串路由,并消除了路由名称中的错误。迁移需要 Kotlin Serialization 插件和 navigation-compose-typesafe 依赖项。

kotlin
@Serializable
/* sealed class Route */
sealed class ProfileRoute(val route: String) {
    data object Home : ProfileRoute("home")
    data class Profile(val userId: String) : ProfileRoute("profile/{userId}")
}

深层链接 — 一种导航机制,允许通过 URL 或 intent-filter 打开应用程序的特定屏幕。在 Navigation Compose 中,深层链接通过 composable() 中的 deepLinks 参数配置,并在 URI 与模式匹配时自动处理。

深层链接定义为 UriPattern 列表:"https://example.com/profile/{userId}"。URI 中的参数自动映射到路由参数。NavController 在应用程序启动时(通过 intent)和运行期间(通过隐式深层链接)处理深层链接。为了处理待处理的深层链接,在图初始化后在 NavController 中使用 handleDeepLink()

根据 Google 的建议,深层链接推荐用于:推送通知(Firebase Dynamic Links)、电子邮件验证、内容共享和从 Web 链接导航。对于 Android 12+,使用 Digital Asset Links 验证深层链接的权威性。AndroidManifest.xml 必须包含带有 autoVerify="true" 的 intent-filter,以便无需对话框即可打开链接。

kotlin
composable(
    route = "profile/{userId}",
    arguments = listOf(navArgument("userId") { type = NavType.StringType }),
    deepLinks = listOf(
        navDeepLink { uriPattern = "https://example.com/profile/{userId}" }
    )
) { backStackEntry ->
    ProfileScreen(userId = backStackEntry.arguments?.getString("userId") ?: "")
}

Navigation Compose 中深层链接的限制:该库不支持延迟的深层链接 — 只有在 NavHost 完全构建图之后,深层链接才会被处理。如果深层链接在图初始化之前到达,则需要通过 intent?.data 延迟并在 LaunchedEffect 中处理。对于 Firebase Dynamic Links,请将 Firebase Dynamic Links SDK 与 Navigation Compose 结合使用。

屏幕之间的过渡动画

Navigation Compose 通过 composable() 中的 enterTransitionexitTransitionpopEnterTransitionpopExitTransition 参数支持过渡动画。动画通过 Compose Animation API 实现:fadeIn、slideInHorizontally、expandIn 等。默认情况下,动画是禁用的 — 屏幕立即切换。

典型的动画场景:slideInHorizontally 用于向前导航(屏幕从右侧进入),slideOutHorizontally 用于返回(屏幕向右退出)。对于 BottomNavigation,更常使用无滑动淡入淡出动画。动画通过 NavHost 设置,如果没有指定单独的动画,则应用于所有 composable。

kotlin
NavHost(
    navController = navController,
    startDestination = "home",
    enterTransition = { slideInHorizontally() + fadeIn() },
    exitTransition = { slideOutHorizontally() + fadeOut() },
    popEnterTransition = { fadeIn() },
    popExitTransition = { slideOutHorizontally() + fadeOut() }
) { /* composable */ }

可以通过直接在 composable() 中传递动画参数来为每个 composable 单独重写动画。重要提示:动画不应与系统返回按钮动画冲突。对于共享元素过渡,需要 accompanist-navigation-animation 库或通过 Modifier.graphicsLayer 的自定义实现。根据 Android Developers (2025) 的数据,80% 的生产应用程序使用水平滑动动画进行标准导航。

常见问题

Navigation Compose 与 View 的 Navigation Component 有何不同?

Navigation Compose 无需 Fragment 即可工作,使用 composable 函数和 Kotlin DSL 构建图。Navigation Component (View) 基于 FragmentManager 和 XML 图。Compose 版本更简单、更快,并且没有 Fragment 生命周期。View 的 Navigation Component 仅适用于混合应用程序。

如何在屏幕之间传递复杂对象?

建议传递对象 ID 并通过 ViewModel 与 SavedStateHandle 加载数据。如果对象很简单 — 通过 kotlinx.parcelize 使用 Parcelable。直接通过参数(Bundle)传递大对象限制在约 1 MB,可能导致 TransactionTooLargeException。

Navigation Compose 支持嵌套图吗?

是的,通过 NavHost 内的 navigation(route, startDestination) 函数。嵌套图有自己的 startDestination,并在公共路由前缀下合并。这允许为每个功能模块组织具有隔离图的模块化架构。

如何在 Navigation Compose 中处理系统返回按钮?

NavController 通过 Compose 的 BackHandler 自动处理返回按钮。在按下返回按钮时调用 navController.popBackStack()。对于自定义处理(确认退出),在调用 popBackStack() 之前使用 BackHandler(enabled = condition) { callback }。

Navigation Compose 可以与 Jetpack Compose Multiplatform 一起使用吗?

目前,Navigation Compose 不支持 Compose Multiplatform。对于跨平台项目的 iOS 部分,请使用 Voyager 或 Decompose。Google 正在开发 KMP 支持,但没有发布日期。对于仅限 Android 的项目,Navigation Compose 是唯一推荐的选项。

总结

  • Navigation Compose — 用于在 Compose 中进行声明式导航的 Jetpack 库,通过路由图和 NavController 工作
  • NavController 管理返回栈并提供 navigate、popBackStack 方法进行导航
  • NavHost 通过 composable() 将控制器与图连接,支持用于模块化架构的嵌套图
  • 参数通过 NavType 传递,支持 String、Int、Parcelable 以及 Kotlin Serialization 的类型安全导航
  • 深层链接通过 navDeepLink 与 UriPattern 配置,用于来自 URL 和推送通知的外部导航
  • 动画过渡通过 enterTransition、exitTransition 使用 Compose Animation API 设置
  • 该库不支持 KMP 和 BottomNavigation 的多返回栈(无需额外配置)

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读