当前位置: 首页 > news >正文

Android Jetpack 组件库 ->Jetpack Navigation (下)

目录

1. Navigation 简介与背景

1.1 为什么需要 Navigation?

1.2 Navigation 的优势

2. 核心概念与架构

2.1 核心组件

2.2 导航类型

3. 基础使用与实践

3.1 项目配置

3.2 基本导航操作

3.3 参数传递详解

4. 高级特性

4.1 返回栈管理

4.2 深层链接(Deep Link)

4.3 底部导航栏集成

5. 实际项目应用

5.1 单 Activity + 多 Fragment 架构

5.2 多模块化项目

5.3 动态导航

6. 最佳实践与注意事项

7. 常见问题与解决方案

7.1 Fragment 重复创建

7.2 参数丢失

7.3 返回栈异常

7.4 多 NavHost 场景

8. 总结


上一篇:

Android Jetpack 组件库 ->Jetpack Navigation (上)_android jetpack navigation-CSDN博客

1. Navigation 简介与背景

1.1 为什么需要 Navigation?

传统导航的问题:

 // 传统方式 - 手动管理 Fragmentclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 手动添加 FragmentsupportFragmentManager.beginTransaction().add(R.id.container, HomeFragment()).commit()}fun navigateToDetail(itemId: String) {// 手动处理导航逻辑val fragment = DetailFragment.newInstance(itemId)supportFragmentManager.beginTransaction().replace(R.id.container, fragment).addToBackStack(null).commit()}}

问题:

  • 代码重复且容易出错
  • 难以管理返回栈
  • 参数传递不安全
  • 难以处理深层链接
  • 测试困难

1.2 Navigation 的优势

// Navigation 方式 - 声明式导航// 在导航图中定义<actionandroid:id="@+id/action_home_to_detail"app:destination="@id/detailFragment" />// 在代码中使用findNavController().navigate(R.id.action_home_to_detail)

优势:

  • ✅ 可视化编辑导航图
  • ✅ 类型安全的参数传递
  • ✅ 自动管理返回栈
  • ✅ 支持深层链接
  • ✅ 易于测试
  • ✅ 支持动画和转场

2. 核心概念与架构

2.1 核心组件

xml

Apply

<!-- Navigation 架构图 -->

Navigation Graph (导航图)

    ↓

NavController (导航控制器)

    ↓

NavHost (导航容器)

    ↓

NavDestination (导航目标)

详细说明:

  1. Navigation Graph(导航图)
  • 定义应用的所有导航路径
  • 可视化编辑界面
  • XML 格式存储
  1. NavController(导航控制器)
  • 管理导航操作
  • 处理返回栈
  • 执行导航动作
  1. NavHost(导航容器)
  • 显示当前目标
  • FragmentContainerView 实现
  • 管理 Fragment 生命周期
  1. NavDestination(导航目标)
  • 具体的导航目标(Fragment/Activity)
  • 包含参数定义
  • 支持深层链接

2.2 导航类型

<!-- 三种导航类型 -->

<fragment android:id="@+id/fragment_dest" />

<activity android:id="@+id/activity_dest" />

<navigation android:id="@+id/nested_nav" />


3. 基础使用与实践

3.1 项目配置

步骤1:添加依赖

// build.gradle (app)dependencies {def nav_version = "2.7.5"// Navigation Fragmentimplementation "androidx.navigation:navigation-fragment-ktx:$nav_version"implementation "androidx.navigation:navigation-ui-ktx:$nav_version"// Navigation TestingandroidTestImplementation "androidx.navigation:navigation-testing:$nav_version"}// build.gradle (project)plugins {id "androidx.navigation.safeargs.kotlin" version "2.7.5"}

步骤2:创建导航图

<!-- res/navigation/nav_graph.xml --><?xml version="1.0" encoding="utf-8"?><navigation xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/nav_graph"app:startDestination="@id/homeFragment"><!-- 首页 --><fragmentandroid:id="@+id/homeFragment"android:name="com.example.app.HomeFragment"android:label="首页"><actionandroid:id="@+id/action_home_to_detail"app:destination="@id/detailFragment"app:enterAnim="@anim/slide_in_right"app:exitAnim="@anim/slide_out_left" /><actionandroid:id="@+id/action_home_to_profile"app:destination="@id/profileFragment" /></fragment><!-- 详情页 --><fragmentandroid:id="@+id/detailFragment"android:name="com.example.app.DetailFragment"android:label="详情"><argumentandroid:name="itemId"app:argType="string"app:nullable="false"app:defaultValue="0" /><argumentandroid:name="itemName"app:argType="string"app:nullable="true" /><argumentandroid:name="itemPrice"app:argType="float"app:nullable="true" /></fragment><!-- 个人资料页 --><fragmentandroid:id="@+id/profileFragment"android:name="com.example.app.ProfileFragment"android:label="个人资料" /></navigation>

步骤3:设置 NavHost

<!-- activity_main.xml --><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.fragment.app.FragmentContainerViewandroid:id="@+id/nav_host_fragment"android:name="androidx.navigation.fragment.NavHostFragment"android:layout_width="0dp"android:layout_height="0dp"app:defaultNavHost="true"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:navGraph="@navigation/nav_graph" /></androidx.constraintlayout.widget.ConstraintLayout>

3.2 基本导航操作

获取 NavController:

// 在 Fragment 中class HomeFragment : Fragment() {private lateinit var navController: NavControlleroverride fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)// 方法1:通过 findNavController()navController = findNavController()// 方法2:通过 NavHostFragmentnavController = NavHostFragment.findNavController(this)// 方法3:通过 ActivitynavController = (activity as MainActivity).findNavController(R.id.nav_host_fragment)}}

基本导航:

// 简单导航navController.navigate(R.id.detailFragment)// 带参数导航val bundle = Bundle().apply {putString("itemId", "123")putString("itemName", "测试商品")}navController.navigate(R.id.detailFragment, bundle)// 使用 Safe Args(推荐)val action = HomeFragmentDirections.actionHomeToDetail(itemId = "123",itemName = "测试商品",itemPrice = 99.99f)navController.navigate(action)

3.3 参数传递详解

参数类型:

<!-- 支持的数据类型 -->

<argument android:name="stringArg" app:argType="string" />

<argument android:name="intArg" app:argType="integer" />

<argument android:name="floatArg" app:argType="float" />

<argument android:name="boolArg" app:argType="boolean" />

<argument android:name="longArg" app:argType="long" />

<argument android:name="arrayArg" app:argType="string[]" />

<argument android:name="parcelableArg" app:argType="com.example.User" />

<argument android:name="enumArg" app:argType="com.example.UserType" />

接收参数:

class DetailFragment : Fragment() {override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)// 方法1:通过 argumentsval itemId = arguments?.getString("itemId")val itemName = arguments?.getString("itemName")// 方法2:使用 Safe Args(推荐)val args = DetailFragmentArgs.fromBundle(arguments!!)val itemId = args.itemIdval itemName = args.itemNameval itemPrice = args.itemPrice// 使用参数updateUI(itemId, itemName, itemPrice)}private fun updateUI(itemId: String, itemName: String?, itemPrice: Float?) {// 更新界面}}


4. 高级特性

4.1 返回栈管理

// 基本返回navController.popBackStack()// 返回到指定目标navController.popBackStack(R.id.homeFragment, false)// 清除返回栈并导航navController.navigate(R.id.detailFragment) {popUpTo(R.id.homeFragment) { inclusive = true }}// 设置返回栈行为<actionandroid:id="@+id/action_home_to_detail"app:destination="@id/detailFragment"app:popUpTo="@id/homeFragment"app:popUpToInclusive="false" />

4.2 深层链接(Deep Link)

应用内深层链接:

<fragmentandroid:id="@+id/detailFragment"android:name="com.example.app.DetailFragment"><deepLinkandroid:id="@+id/deepLink"app:uri="myapp://detail/{itemId}" /><argumentandroid:name="itemId"app:argType="string" /></fragment>

Web 深层链接:

<fragmentandroid:id="@+id/detailFragment"android:name="com.example.app.DetailFragment"><deepLinkapp:uri="https://myapp.com/detail/{itemId}" /><argumentandroid:name="itemId"app:argType="string" /></fragment>

处理深层链接:

// 在 Activity 中处理class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val navController = findNavController(R.id.nav_host_fragment)// 处理深层链接navController.handleDeepLink(intent)}}

4.3 底部导航栏集成

创建底部导航菜单:

<!-- res/menu/bottom_nav_menu.xml --><menu xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:id="@+id/homeFragment"android:icon="@drawable/ic_home"android:title="首页" /><itemandroid:id="@+id/categoryFragment"android:icon="@drawable/ic_category"android:title="分类" /><itemandroid:id="@+id/profileFragment"android:icon="@drawable/ic_profile"android:title="我的" /></menu>

集成底部导航:

<!-- activity_main.xml --><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.fragment.app.FragmentContainerViewandroid:id="@+id/nav_host_fragment"android:name="androidx.navigation.fragment.NavHostFragment"android:layout_width="0dp"android:layout_height="0dp"app:defaultNavHost="true"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toTopOf="@id/bottom_navigation"app:navGraph="@navigation/nav_graph" /><com.google.android.material.bottomnavigation.BottomNavigationViewandroid:id="@+id/bottom_navigation"android:layout_width="0dp"android:layout_height="wrap_content"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintBottom_toBottomOf="parent"app:menu="@menu/bottom_nav_menu" /></androidx.constraintlayout.widget.ConstraintLayout>

在 Activity 中设置:

        // 监听导航变化navController.addOnDestinationChangedListener { _, destination, _ ->when (destination.id) {R.id.homeFragment -> {// 进入首页}R.id.categoryFragment -> {// 进入分类页}R.id.profileFragment -> {// 进入个人资料页}}}}}


5. 实际项目应用

5.1 单 Activity + 多 Fragment 架构

  • Navigation 最适合单 Activity 架构,所有页面用 Fragment 实现,统一由 NavController 管理。
  • 例如:主界面、详情页、个人中心等都作为 Fragment,Activity 只负责承载 NavHost。

5.2 多模块化项目

  • Navigation 支持 navigation graph 嵌套,可以将不同业务模块的导航图拆分,主导航图通过 <include> 标签引入子导航图,便于团队协作和模块解耦。
<!-- 主导航图 --><navigation ...><include app:graph="@navigation/feature_a_nav" /><include app:graph="@navigation/feature_b_nav" /></navigation>

5.3 动态导航

  • 可以根据业务逻辑动态决定导航目标,例如登录后跳转到不同页面。
 if (user.isLoggedIn) {navController.navigate(R.id.action_to_home)} else {navController.navigate(R.id.action_to_login)}


6. 最佳实践与注意事项

  1. 优先使用 Safe Args
  • 避免 Bundle 传参出错,提升类型安全。
  1. 合理设计导航图结构
  • 避免过深嵌套,保持导航图清晰。
  1. 处理返回栈
  • 善用 popUpTo 和 inclusive,避免页面堆积。
  1. 深层链接支持
  • 方便外部唤起和 App 内跳转。
  1. 动画与转场
  • 提升用户体验,使用自定义动画资源。
  1. 测试导航逻辑
  • 使用 Navigation Testing 库进行单元测试和 UI 测试。

7. 常见问题与解决方案

7.1 Fragment 重复创建

  • 避免在导航时重复 navigate 到同一个目标,可以先判断当前 destination。

7.2 参数丢失

  • 使用 Safe Args,避免 Bundle 传参遗漏或类型错误。

7.3 返回栈异常

  • 检查导航图中 popUpTo 配置,确保返回栈符合预期。

7.4 多 NavHost 场景

  • 多 NavHost 时要分别管理各自的 NavController,避免混淆。

8. 总结

Jetpack Navigation 组件极大简化了 Android 应用的导航开发,提升了代码的可维护性和安全性。

  • 推荐在新项目中优先采用 Navigation 组件,配合单 Activity 架构和 Safe Args 使用。
  • 合理设计导航图,充分利用深层链接、动画、返回栈等高级特性,打造高质量的用户体验。
http://www.dtcms.com/a/300333.html

相关文章:

  • 通过不同坐标系下的同一向量,求解旋转矩阵
  • 深度学习入门(2)
  • 实验-OSPF多区域
  • 告别Vite脚手架局限!MixOne Beta测试招募:你的需求,我们来实现
  • 【Java】基础概念-构造函数详解
  • [Python] -进阶理解7- Python中的内存管理机制简析
  • 基于springboot的在线数码商城/在线电子产品商品销售系统的设计与实现
  • (二)使用 LangChain 从零开始构建 RAG 系统 RAG From Scratch
  • 7月26号打卡
  • Unity GenericMenu 类详解
  • 技术 — 资本双螺旋:AI 时代的投资浪潮与技术突破
  • 模型训练部署流程
  • 电磁兼容三:电磁干扰三要素详解
  • 【大模型框架】LangChain入门:从核心组件到构建高级RAG与Agent应用
  • 系统性学习C语言-第二十三讲-文件操作
  • 渗透艺术系列之Laravel框架(一)
  • Effective C++ 条款03:尽可能使用const
  • 检验类设备中,交叉导轨如何确保加样精度?
  • mysql-数据表-DDL语句
  • Triton源代码分析 - 目录
  • freeRTOS 静态创建任务
  • TIM 输入捕获
  • pip, github 突然连不上?报错和解决方法如下
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-29,(知识点:非易失存储器)
  • 【AI周报】2025年7月26日
  • CUDA杂记--FP16与FP32用途
  • MoE替代LLM
  • linux内核电源管理
  • 面试150 加一
  • 一文速通《多元函数微分学》