游乐游手机版
首页/AI教程/文章详情

Android Navigation Component从零到一页面跳转清晰教程

时间:2026-06-29 15:30
Android页面跳转随项目规模增长易混乱。JetpackNavigationComponent将导航逻辑集中于导航图,由NavController统一管理跳转、返回栈和参数传递,支持Toolbar、BottomNavigationView及深链接,并借助SafeArgs保证类型安全。该组件适用于Fragment较多、跳转关系复杂的项目,能显著提升代码可维护

在 Android 项目里,页面跳转这事儿,一开始往往都挺简单:A 页面开 B 页面,一个 Intent 搞定;Fragment 之间切来切去,也就是 FragmentTransaction 里一句 replace。小项目这么搞确实没什么压力,但页面一多起来——跳转关系、返回栈、参数传递、还有深链接,这些东西搅在一起,很快就能把人绕晕。

[Android 从零到一] Na vigation Component:让页面跳转更清晰

Jetpack 里的 Navigation Component,就是专门来处理这个麻烦的。它不是要取代 Activity 或 Fragment,而是把“页面之间怎么走”这件事统一管起来,让整个跳转逻辑更清晰,也更容易维护。

1. 为什么需要 Navigation Component

咱们先看看传统写法里那些让人头疼的地方。

比如 Fragment 跳转,通常得这么写:

supportFragmentManager.beginTransaction()
    .replace(R.id.container, DetailFragment())
    .addToBackStack(null)
    .commit()

这代码跑是跑得通,但毛病也不少:

  • 跳转逻辑散落在各个页面里,找起来费劲
  • 返回栈得自己手动维护
  • 参数传递基本靠 Bundle,手写 key,一不小心就写错
  • 页面之间的关系一点都不直观,后面维护成本越来越高
  • 遇到深链接、底部导航、多返回栈这些场景,代码很容易就写乱了

Navigation Component 的核心思路很简单:把导航关系抽出来,放到一个导航图里,统一交给 NavController 来执行跳转。

换句话说,页面只管说“我要去哪儿”,至于返回栈怎么管理、目标页面怎么找到、参数怎么传,这些脏活累活全交给导航组件来处理。

2. Navigation Component 的三个核心角色

Navigation Component 里最常碰到的三个概念是:

  • NavHost:页面容器,负责承载不同的目的地
  • NavController:导航控制器,负责执行跳转和返回
  • NavGraph:导航图,描述页面之间的路线关系

可以这么理解:NavGraph 定义路线,NavHost 负责显示页面,NavController 来执行跳转。分清楚这三者的职责,后面就好办了。

3. 添加依赖

在模块的 build.gradle 里加上依赖:

dependencies {
    implementation("androidx.navigation:navigation-fragment-ktx:2.7.7")
    implementation("androidx.navigation:navigation-ui-ktx:2.7.7")
}

如果项目用了版本目录,最好把版本统一放到 libs.versions.toml 里管理。实际项目里建议统一版本管理,免得多个 Jetpack 组件版本打架。

4. 创建导航图

res/navigation 目录下创建一个导航图,比如 nav_graph.xml




    
        
    

    

这里我们定义了两个页面:homeFragmentdetailFragmentapp:startDestination 指定了进入导航容器后默认显示哪个页面,而 action_home_to_detail 就是一条从首页到详情页的路径。

5. 在布局中放入 NavHost

Activity 的布局里需要一个 FragmentContainerView 作为导航容器:

几个属性值得留意:

  • android:name 指定这里用的是 NavHostFragment
  • app:navGraph 绑定刚才创建的导航图
  • app:defaultNavHost="true" 表示系统返回键会优先交给这个导航容器处理

这样,一个基础的导航容器就搭好了。

6. 执行页面跳转

在 Fragment 里通过 findNavController() 拿到导航控制器:

class HomeFragment : Fragment(R.layout.fragment_home) {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.findViewById

相比手写 FragmentTransaction,这段代码的意思更直接:点击按钮,按导航图里定义的 action 跳到详情页。页面之间的关系不再分散在各处,打开 nav_graph.xml 一眼就能看清楚整个跳转链路。

7. 页面返回怎么处理

Navigation Component 会自动打理返回栈。从首页进详情页,按系统返回键默认会回到首页。如果你想在代码里主动返回,可以这么写:

findNavController().popBackStack()

想返回到指定页面的话:

findNavController().popBackStack(R.id.homeFragment, false)

第二个参数控制目标页面本身是否也要弹出:

  • false:回到目标页面,目标页面保留
  • true:连目标页面一起弹出

这个参数在实际开发里特别容易弄错,建议用的时候多留个心眼。

8. 页面参数传递

最基础的方式还是用 Bundle

val bundle = bundleOf("articleId" to 1001)
findNavController().navigate(R.id.action_home_to_detail, bundle)

在目标页面读取:

val articleId = requireArguments().getInt("articleId")

这种方法简单直接,但缺点也很明显:key 是字符串,类型得自己保证。项目大了以后,强烈建议换成 Safe Args。

9. 使用 Safe Args 提升安全性

Safe Args 是 Navigation Component 配套的参数安全插件。它根据导航图自动生成类型安全的跳转代码。

添加插件后,在导航图里定义参数:


    

跳转时就可以写成:

val action = HomeFragmentDirections.actionHomeToDetail(articleId = 1001)
findNavController().navigate(action)

详情页读取参数:

val args: DetailFragmentArgs by navArgs()
val articleId = args.articleId

这样做的好处很明显:

  • 参数名不容易写错
  • 参数类型由编译器帮你检查
  • 重构的时候更安全
  • 跳转代码读起来也更清爽

10. 和 Toolbar 配合

Navigation Component 可以跟 Toolbar 联动,自动处理标题和返回按钮:

val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
setupActionBarWithNavController(navController)

然后重写:

override fun onSupportNavigateUp(): Boolean {
    return findNavController(R.id.nav_host_fragment).navigateUp()
            || super.onSupportNavigateUp()
}

这样一来,进入二级页面时顶部的返回按钮就能自动跟着导航栈走了。

如果项目用的是 Toolbar 而不是默认的 ActionBar,可以换成:

toolbar.setupWithNavController(navController)

11. 和 BottomNavigationView 配合

底部导航是 Navigation Component 很常见的应用场景:

bottomNavigationView.setupWithNavController(navController)

只要 BottomNavigationView 里 menu item 的 id 和导航图里的 destination id 一一对应,组件就能自动完成切换。

比如:

这里的 android:id 必须和导航图中的 homeFragment 保持一致。这个约定很重要——id 对不上,点击底部导航时就找不到对应的页面。

12. 深链接支持

Navigation Component 可以直接在导航图中配置 deep link:


    

当外部链接匹配这个规则时,可以直接打开详情页,并把路径里的参数传进来。

深链接适合这些场景:

  • 推送通知点击后跳转到指定页面
  • 浏览器链接直接打开 App 内页面
  • 分享链接回流到 App
  • 活动页、内容页通过外部链接直接唤起

不过要注意,对深链接传进来的参数一定要做校验,别直接信任外部值。

13. 常见坑

13.1 在错误的 Fragment 上找 NavController

如果页面结构比较复杂,比如 Fragment 里又嵌套 Fragment,很容易拿错 NavController。一般从正确的 View 或宿主 Fragment 获取:

view.findNavController()

或者在 Activity 中通过 NavHostFragment 来拿。

13.2 重复点击导致多次跳转

按钮快速点击时,可能连续执行多次 navigate(),结果嗖嗖地打开了多个相同页面。实际项目里可以做点击防抖,或者在跳转前检查当前 destination:

val navController = findNavController()
if (navController.currentDestination?.id == R.id.homeFragment) {
    navController.navigate(R.id.action_home_to_detail)
}

13.3 返回栈和预期不一致

涉及登录页、首页、支付成功页这类需要清空历史栈的场景,一定要认真配置 popUpTo

比如登录成功后进入首页,并清掉登录页:

popUpToInclusive="true" 表示把 loginFragment 自己也从返回栈里移除。这样用户在首页按返回键时,就不会莫名其妙地回到登录页了。

13.4 把导航图写得过大

导航图不是越大越好。大型项目里,把所有页面塞进一个导航图,维护起来照样乱。更合理的做法是按业务模块拆分,比如:

  • 首页模块导航图
  • 登录模块导航图
  • 订单模块导航图
  • 我的页面导航图

每个导航图只负责一个相对独立的业务范围,这样更清晰。

14. 什么时候适合用 Navigation Component

适合使用的场景:

  • Fragment 页面比较多
  • 页面跳转关系比较复杂
  • 需要底部导航、抽屉导航、深链接
  • 希望统一管理返回栈
  • 想减少手写 FragmentTransaction 的代码

不一定需要使用的场景:

  • 项目很小,只有一两个页面
  • 页面完全由 Compose Navigation 管理
  • 团队已经有成熟的自研路由方案
  • 业务强依赖跨模块动态路由

所以,Navigation Component 不是所有项目的唯一答案,但对于大多数采用 Jetpack 风格的中小型 Android 项目来说,它确实是非常顺手的选择。

15. 小结

Navigation Component 解决的不是“能不能跳转”的问题,而是“页面跳转能不能做到清晰、统一、好维护”。

它把页面关系集中到导航图里,用 NavController 统一执行跳转,并且内置了返回栈、参数传递、Toolbar、BottomNavigationView、Deep Link 等一系列能力。掌握了它,Android 页面导航就能从零散的手写事务,变成一种结构化的页面流转管理。

对于刚开始学 Jetpack 的开发者,可以先记住一句话:导航图是路书,NavHost 是页面的舞台,NavController 是那个调度员。 理解了这一点,再去看导航图、NavHost、NavController,一切就都顺了。

来源:https://developer.aliyun.com/article/1744109
上一篇循环工程的代价:LLM可用性靠工程Token买来 下一篇WorkManager:高效可靠的安卓后台任务调度
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
Windows Docker Desktop RabbitMQ生产级部署完整指南
AI教程 · 2026-06-29

Windows Docker Desktop RabbitMQ生产级部署完整指南

前言 在 Windows 本地开发环境中,直接安装 RabbitMQ 确实颇为周折:需要单独配置 Erlang 运行环境、手动管理环境变量、服务启停全凭手工操作。更令人困扰的是,版本兼容冲突、端口占用、环境不一致等问题层出不穷。笔者见过不少开发者为搭建环境就得耗费整整半天时间。 相比之下,借助 Do

AI搜索重构制造业采购逻辑的阿里云企业级GEOCMS优化实践
AI教程 · 2026-06-29

AI搜索重构制造业采购逻辑的阿里云企业级GEOCMS优化实践

先分享一个切实感受。过去两年,我们与福建制造企业合作较为频繁,发现一个非常突出的现象:超过80%的企业官网,产品参数仍然存放在PDF或图片中。AI爬虫?根本无法抓取。这些企业技术实力不弱、资质证照齐全、应用案例也丰富,但在AI搜索这一全新战场上,它们几乎处于隐身状态。 一、一个正在发生的行业变化 A

阿里云Token Plan团队版功能价格与省钱购买指南
AI教程 · 2026-06-29

阿里云Token Plan团队版功能价格与省钱购买指南

阿里云百炼近期推出了名为“Token Plan 团队版”的全新服务,这一服务专为企业与开发者量身打造,定位为AI大模型订阅平台。通过引入Credits作为统一计量单位,将文本生成、图像生成等多模态AI能力纳入单一计费体系,同时无缝兼容主流AI编程工具及智能体(Agent)生态系统。其核心亮点包括:全

阿里云物联网.NET Core客户端位置信息上报
AI教程 · 2026-06-29

阿里云物联网.NET Core客户端位置信息上报

阿里云物联网平台的位置服务并非一个完全独立的功能模块。位置信息可包含二维坐标与三维坐标,而位置数据的来源本质上是借助设备属性进行上传。换言之,若要让设备上报位置,您需先将其视为一个普通属性进行处理。 1)添加二维位置数据 操作过程十分简洁。进入数据分析 → 空间数据可视化 → 二维数据,点击添加,将

年阿里云服务器选型配置与网站部署全攻略
AI教程 · 2026-06-29

年阿里云服务器选型配置与网站部署全攻略

2026年,阿里云服务器生态已高度成熟,形成了清晰的轻量应用服务器与ECS云服务器两大产品阵营。无论你是计划搭建个人博客、企业官网,还是运营电商平台、进行应用开发,基本都能找到理想的解决方案。本指南将从服务器选型、配置选择、部署流程到安全运维,系统梳理2026年最实用的操作要点,帮助你少走弯路,让网