Navigation Component — 介绍,NavHost 和 Navigation Graph

作者: IT Sectr 发布日期: 2026-02-22 阅读时间: 7 分钟

Navigation Component — Android Jetpack 库,用于实现应用程序屏幕之间的导航。该组件集中管理片段堆栈、深层链接和参数传递。自 2018 年起成为 Jetpack 的一部分,并被 Google 推荐用于所有新项目。更多信息请阅读 Google 官方指南

要点

  • Navigation Component — 用于 Android 屏幕之间集中式导航的 Jetpack 库
  • NavGraph — 描述所有屏幕及其之间连接的 XML 资源
  • NavHostFragment — Activity 布局中显示当前导航屏幕的容器
  • NavController — 导航管理对象:navigate、popBackStack、navigateUp
  • Safe Args — 用于屏幕之间类型安全参数传递的 Gradle 插件

什么是 Navigation Component?

Navigation Component — Android Jetpack 库 (androidx.navigation),提供统一的导航 API。包含三个关键元素:Navigation Graph(导航图)、NavHostFragment(屏幕容器)和 NavController(过渡控制器)。该组件自动管理返回堆栈并支持深层链接。

在 Navigation Component 之前,开发人员通过 FragmentManager 手动管理片段。这导致代码碎片化:每个屏幕有自己的导航规则,返回堆栈状态不同,深层链接需要单独实现。Navigation Component 统一了这些场景。根据 Google 的数据(2026),该库已安装在 90% 的新 Android 项目中。

Navigation Component 与其他 Jetpack 库集成:LiveData、ViewModel、Material Design。支持 XML 片段和通过 navigation-compose 扩展的 Jetpack Compose。稳定版本 — 2.8.x(2025),最低 Android 版本 — API 14。

NavGraph — XML 资源 (res/navigation/nav_graph.xml),定义应用程序的所有屏幕及其之间的连接。每个屏幕是一个节点(destination),可以是 Fragment、Activity 或 Composable。节点之间的连接称为 action,指定过渡方向。

xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    app:startDestination="@+id/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name=".HomeFragment"
        android:label="首页"
        tools:layout="@layout/fragment_home">
        <action
            android:id="@+id/action_home_to_detail"
            app:destination="@+id/detailFragment"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />
    </fragment>

    <fragment
        android:id="@+id/detailFragment"
        android:name=".DetailFragment"
        android:label="详情"
        tools:layout="@layout/fragment_detail">
        <argument android:name="itemId"
            app:argType="integer"
            android:defaultValue="0" />
    </fragment>
</navigation>

startDestination 属性设置启动时显示的第一个屏幕。Action 定义目标 destination 和可选的动画。参数(argument)描述传递到屏幕的参数 — 类型和默认值。

NavHostFragment — 放置在 Activity 布局中并显示当前导航屏幕的容器。NavHostFragment 在调用 NavController.navigate() 时自动切换片段。NavController — 管理导航的对象:过渡、返回、检查当前路由。

kotlin
// Layout Activity: activity_main.xml
// <androidx.fragment.app.FragmentContainerView
//     android:id="@+id/nav_host_fragment"
//     android:name="androidx.navigation.fragment.NavHostFragment"
//     app:navGraph="@navigation/nav_graph"
//     app:defaultNavHost="true" />

class MainActivity : AppCompatActivity() {

    private val navController by lazy {
        (findViewById<NavHostFragment>(R.id.nav_host_fragment))
            .navController
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // NavigationUI 将 NavController 与 AppBar 连接
        setupActionBarWithNavController(navController)
    }

    // 切换到详情屏幕
    fun openDetail(itemId: Long) {
        val bundle = Bundle().apply {
            putLong("itemId", itemId)
        }
        navController.navigate(R.id.action_home_to_detail, bundle)
    }

    override fun onSupportNavigateUp() = 
        navController.navigateUp() || super.onSupportNavigateUp()
}

app:defaultNavHost="true" — 重要属性:拦截系统「返回」按钮并将控制权交给 NavController。NavigationUI — 用于将 NavController 连接到 AppBar、BottomNavigationView、NavigationDrawer 的实用工具。setupActionBarWithNavController 在嵌套屏幕上启用「向上」箭头。

Navigation Component 支持自定义过渡动画,在 action 中或通过编程定义。动画由四个属性定义:enterAnim(新屏幕出现)、exitAnim(当前屏幕消失)、popEnterAnim(返回时出现)和 popExitAnim(返回时消失)。

xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="100%"
        android:toXDelta="0%"
        android:duration="300" />
</set>

// 带动画的编程过渡
val navOptions = NavOptions.Builder()
    .setEnterAnim(R.anim.slide_in_right)
    .setExitAnim(R.anim.slide_out_left)
    .setPopEnterAnim(R.anim.slide_in_left)
    .setPopExitAnim(R.anim.slide_out_right)
    .build()

navController.navigate(R.id.detailFragment, args, navOptions)

动画在 FragmentTransaction 级别与 Fragment 一起工作。对于 Jetpack Compose,动画通过 NavOptionsCompat 使用 Compose Animation 设置。Navigation Component 不限制动画类型 — 支持 translate、scale、alpha 及其组合。

Safe Args:类型安全的参数

Safe Args — Gradle 插件,用于屏幕之间类型安全的数据传输。插件分析 NavGraph,生成具有特定类型字段的 Directions 和 Args 类。在编译阶段检查类型匹配 — MissingArgumentException 错误在应用程序启动前被检测到。

kotlin
// build.gradle (module)
plugins {
    id 'androidx.navigation.safeargs.kotlin'
}

// Safe Args 生成:DetailFragmentArgs、HomeFragmentDirections
// 在 HomeFragment 中使用:
val action = HomeFragmentDirections
    .actionHomeToDetail(itemId = 42L)
findNavController().navigate(action)

// 在 DetailFragment 中使用:
private val args: DetailFragmentArgs by navArgs()
// args.itemId 类型为 Long,不能传递 null

override fun onViewCreated(...) {
    super.onViewCreated(...)
    loadItem(args.itemId)
}

navArgs() — Kotlin 委托,用于在 Fragment 或 Activity 中获取参数。插件支持原始类型、字符串、Parcelable、Serializable、Enum 和数组。对于复杂对象,使用 ID 传递并从 ViewModel 或数据库加载。

Deep Link — 打开应用程序特定屏幕的外部链接。Navigation Component 通过 NavGraph 中的 app:deepLink 属性处理深层链接。系统创建一个 PendingIntent,将导航堆栈恢复到目标屏幕,如果应用程序未运行则创建新堆栈。

xml

<fragment android:id="@+id/profileFragment"
    android:name=".ProfileFragment">
    <deepLink
        app:uri="https://example.com/profile/{userId}" />
    <argument
        android:name="userId"
        app:argType="string" />
</fragment>

// 编程创建 Deep Link
val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.profileFragment)
    .setArguments(Bundle().apply {
        putString("userId", "user_123")
    })
    .createPendingIntent()

深层链接支持带有路径和查询参数的 URI 模板、intent action 和 mime type。占位符 ({userId}) 自动映射到 destination 参数。Navigation Component 还通过 AndroidManifest 处理隐式深层链接 — 只需向带有 NavHostFragment 的 Activity 添加 intent-filter 即可。

Navigation Compose (androidx.navigation:navigation-compose) — Navigation Component 对 Jetpack Compose 的扩展。API 保留了 NavController 和 NavHost 的概念,但屏幕是 Composable 函数而非 Fragment。NavHost 为每个路由接收 composable lambda。

kotlin
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyAppTheme {
                val navController = rememberNavController()
                NavHost(
                    navController = navController,
                    startDestination = "home"
                ) {
                    composable("home") {
                        HomeScreen(
                            onItemClick = { id ->
                                navController.navigate("detail/$id")
                            }
                        )
                    }
                    composable(
                        route = "detail/{itemId}",
                        arguments = listOf(
                            navArgument("itemId") {
                                type = NavType.LongType
                            }
                        )
                    ) { backStackEntry ->
                        val itemId = backStackEntry
                            .arguments?.getLong("itemId") ?: 0L
                        DetailScreen(itemId = itemId)
                    }
                }
            }
        }
    }
}

Navigation Compose 使用字符串路由而不是 id。参数通过路由模板 ("detail/{itemId}") 传递并从 backStackEntry 中提取。rememberNavController() 在重组时保留 NavController。对于 Compose 中的 Type Safety,推荐使用 navigation-compose-type-safety 模块(实验性)。

常见问题

Navigation Component 中的 NavHost 是什么?

NavHost — 用于显示导航屏幕的容器。通过 XML 布局中的 NavHostFragment 实现。NavHost 跟踪 NavGraph 中的当前屏幕并管理过渡。每个 Activity 包含一个 NavHostFragment。

Safe Args 比 Bundle 好在哪里?

Safe Args — Gradle 插件,生成类型安全的参数类。Bundle 需要手动指定键和类型,导致运行时错误。Safe Args 在编译阶段检查类型并自动序列化数据。

如何通过 Navigation Component 传递复杂对象?

复杂对象通过 ViewModel(屏幕之间共享)或通过数据库传递 ID 来传递。Safe Args 只支持原始类型、字符串和 Parcelable。Google 建议避免通过导航参数传递大型对象。

Navigation Component 中的 Deep Link 如何工作?

Deep Link 在 NavGraph 中通过 app:deepLink 属性配置。Navigation Component 自动处理传入的链接,通过 NavDeepLinkBuilder 创建 PendingIntent,并将导航堆栈恢复到目标屏幕。支持 URI、intent action 和 mime type。

Navigation Component 可以用于 Jetpack Compose 吗?

可以。Navigation Compose (androidx.navigation:navigation-compose) 为 Compose 提供 NavHost。API 类似于 XML 版本,但屏幕是 Composable 函数。NavController 在两个版本中使用方式相同。Google 推荐在 Compose 新项目中使用 Navigation Compose。

总结

  • Navigation Component — Android Jetpack 库,使用 NavController、NavHost 和 NavGraph 进行集中式导航
  • NavGraph — XML 图,描述所有屏幕(destination)及其之间的连接(action)
  • NavHostFragment — Activity 布局中的容器,支持「返回」按钮的 defaultNavHost 属性
  • Safe Args — Gradle 插件,用于类型安全的参数传递,编译时进行类型检查
  • Deep Links 支持 URI、intent action 和 mime type,自动恢复导航堆栈
  • Navigation Compose — Jetpack Compose 扩展,使用字符串路由和 composable 屏幕
  • Navigation Component 是 Google 在新 Android 项目中唯一推荐的导航方式

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

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

讨论项目

另请阅读