Android Jetpack Navigation 详解

920 阅读3分钟

Jetpack Navigation 组件简化了 Android 应用内的导航逻辑,统一管理 Fragment、Activity 的切换和回退栈。本文会从其核心功能、使用示例、适用场景、注意事项及版本兼容性等方面进行讲解。

一、核心概念与组件

1. 导航图(NavGraph)

XML 文件定义所有页面(目的地)及导航关系,支持参数传递和动画。

2. NavController

控制导航操作(如跳转、回退),管理回退栈。

3. NavHost

容器(如 NavHostFragment),用于显示导航图中的目的地(通常是 Fragment)。

4. Safe Args

类型安全的参数传递插件,生成导航操作的代码类。

二、使用示例

新建Activity -> Bottom Navigation Views Activity 即可.

1. 基础配置

  • 添加依赖

    // build.gradle (app)
    dependencies {
        implementation "androidx.navigation:navigation-fragment-ktx:2.7.7"
        implementation "androidx.navigation:navigation-ui-ktx:2.7.7"
        // Safe Args 插件
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.7.7"
    }
    
  • 启用 Safe Args(在 app/build.gradle):

    plugins {
        id 'androidx.navigation.safeargs.kotlin'
    }
    

2. 创建导航图(nav_graph.xml)

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

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.HomeFragment"
        android:label="Home">
        <action
            android:id="@+id/action_to_detail"
            app:destination="@id/detailFragment"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left" />
    </fragment>

    <fragment
        android:id="@+id/detailFragment"
        android:name="com.example.DetailFragment"
        android:label="Detail">
        <argument
            android:name="itemId"
            app:argType="integer"
            android:defaultValue="-1" />
    </fragment>
</navigation>

3. 在 Activity 中设置 NavHost

<!-- activity_main.xml -->
<androidx.fragment.app.FragmentContainerView
    android:id="@+id/nav_host"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:navGraph="@navigation/nav_graph" />

4. 执行导航操作

  • 从 HomeFragment 跳转到 DetailFragment

    // 使用 Safe Args 传递参数
    val action = HomeFragmentDirections.actionToDetail(itemId = 123)
    findNavController().navigate(action)
    
  • 接收参数(DetailFragment 中)

    private val args: DetailFragmentArgs by navArgs()
    val itemId = args.itemId
    

5. 底部导航栏集成

// MainActivity.kt
val navController = findNavController(R.id.nav_host)
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNav.setupWithNavController(navController)

6. 细节处理

// 去除BottomNavigationView item长按吐司问题
(binding.navView.getChildAt(0) as ViewGroup).children.forEach {
    it.setOnLongClickListener { true }
}
//设置icon大小
binding.navView.itemIconSize =
    resources.getDimensionPixelSize(R.dimen.home_icon_size)
// 取消BottomNavigationView item图标着色
binding.navView.itemIconTintList = null
// 设置字体颜色
val colors = intArrayOf(
    resources.getColor(R.color.color_999999, theme),
    resources.getColor(R.color.theme_red, theme)
)
binding.navView.itemTextColor = ColorStateList(
    arrayOf(
        intArrayOf(-android.R.attr.state_checked),
        intArrayOf(android.R.attr.state_checked)
    ),
    colors
)

三、适用场景

1. 单 Activity 多 Fragment 架构

适用于主界面为底部导航栏或抽屉菜单的应用。

2. 条件性导航

根据用户登录状态跳转不同页面。

3. 深层链接(DeepLink)

从通知或网页直接打开应用内特定页面。

<deepLink app:uri="example://detail/{itemId}" />

4. 动态导航

根据业务逻辑动态修改导航图。

四、注意事项

1. 回退栈管理

  • 使用 popUpTo 和 popUpToInclusive 控制回退栈。
<action
    android:id="@+id/action_to_login"
    app:destination="@id/loginFragment"
    app:popUpTo="@id/homeFragment"
    app:popUpToInclusive="true" />

2. ViewModel 作用域

  • 使用 by activityViewModels() 共享 Activity 级数据。

3. 避免内存泄漏

  • 在 Fragment 的 onDestroyView() 中取消数据监听。

4. 动画冲突

  • 确保导航动画与 Fragment 内部动画不冲突。

5. Safe Args 限制

  • 复杂对象需实现 Parcelable 或 Serializable

五、版本兼容性

Navigation 版本最低 Android API主要特性
2.3.xAPI 14 (Android 4.0)支持 Fragment、Activity、深层链接、动态导航图。
2.4.0+API 21 (Android 5.0)支持多返回栈、改进动画兼容性。
2.7.xAPI 21 (Android 5.0)增强与 Compose 集成、优化回退栈处理。
  • AndroidX 要求:Navigation 必须与 AndroidX 库配合使用,不支持旧版 Support 库。
  • Java 8+ :从 2.4.0 开始需启用 Java 8。

六、常见问题解决

1. 找不到目的地 ID

  • 确保 nav_graph.xml 中的 ID 与代码中一致。

2. 导航重复跳转

  • 使用 navController.currentDestination?.id 检查当前页面。

3. 深层链接不生效

  • 在 AndroidManifest.xml 中声明 nav-graph
<activity android:name=".MainActivity">
    <nav-graph android:value="@navigation/nav_graph" />
</activity>

七、总结

  • 优势:统一导航逻辑、简化代码、支持复杂跳转和 Safe Args。
  • 推荐场景:单 Activity 应用、底部导航、需要动态导航逻辑。
  • 最佳实践:结合 ViewModel 管理状态、使用 Safe Args 传递参数、合理设计导航图层级。

通过合理使用 Navigation 组件,可显著提升应用导航的可维护性和用户体验。

更多分享

  1. Android Jetpack Room 新手使用指南
  2. Android Jetpack WorkManager 详解
  3. Android Jetpack Security 使用入门指南
  4. Android 详解:高频使用的 8 种设计模式的核心思想和代码实现
  5. 一文带你吃透Kotlin中 lateinit 和 by lazy 的区别和用法
  6. Android ContentProvider 详解及结合 Jetpack Startup 的优化实践