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

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.xdnf.cn/news/16383.html

相关文章:

  • 从治理到共情——平台伦理的乡村共建之路
  • 在 C# 中,问号 ? 的一些作用
  • HTML初学者第五天
  • 启动式service
  • 强化学习(第三课第三周)
  • 在 Scintilla 中为 Squirrel 语言设置语法解析器的方法
  • Kubernetes 配置管理
  • odoo代码分析(一)
  • 认识泛型、泛型类和泛型接口
  • 大语言模型 LLM 通过 Excel 知识库 增强日志分析,根因分析能力的技术方案(2):LangChain + LlamaIndex 实现
  • Java学习第七十七部分——JVM运行时数据区
  • Java同步锁性能优化:15个高效实践与深度解析
  • 7月26号打卡
  • C++/CLI与标准C++的语法差异(一)
  • ASP.NET Core MVC中taghelper的ModelExpression详解
  • Spring Boot 3 如何整合 MinIO 实现分布式文件存储?
  • MyBatis-Plus 通用 Service 详解:IService 与 CRUD 操作全解析
  • PYTHON从入门到实践-15数据可视化
  • 【资讯】2025年软件行业发展趋势:AI驱动变革,云原生与安全成核心
  • PHP框架之Laravel框架教程:1. laravel搭建
  • 亚马逊测评采购:如何打造安全的环境,技术基础关键
  • 2025年渗透测试面试题总结-2025年HW(护网面试) 70(题目+回答)
  • Avantage6.6下载与安装教程
  • 差模干扰 共模干扰
  • 【隧道篇 / IPsec】(7.6) ❀ 01. 利用向导快速建立IPsec安全隧道 (点对点) ❀ FortiGate 防火墙
  • 详解力扣高频SQL50题之550. 游戏玩法分析 IV【中等】
  • ClickHouse高性能实时分析数据库-消费实时数据流(消费kafka)
  • MySQL进阶学习与初阶复习第三天
  • CSS3知识补充
  • 如何高效合并音视频文件(时间短消耗资源少)(二)