1:Navigation 组件 vs 传统 FragmentTransaction
一、核心区别
| 对比维度 | 传统 FragmentTransaction | Jetpack Navigation 组件 |
|---|---|---|
| 管理方式 | 手动代码控制,易出错 | 可视化导航图 + 自动管理 |
| 生命周期 | 需手动处理回退栈、状态保存 | 自动管理回退栈、生命周期 |
| 参数传递 | 手动写 Bundle,类型不安全 | 安全参数传递(Safe Args) |
| 页面跳转 | 硬编码路径,维护困难 | 导航图统一管理,解耦 |
| 动画/过渡 | 手动写动画代码 | 导航图直接配置,统一管理 |
| DeepLink | 复杂,需手动配置 | 原生支持,一行代码搞定 |
| 适用规模 | 简单、少量页面 | 中大型项目、多页面复杂导航 |
二、什么情况下必须用 Navigation 组件?
- 多页面、模块化项目
页面超过 5 个、有嵌套导航、多模块跳转,传统写法会变成“屎山”。 - 需要统一管理导航逻辑
比如登录拦截、全局跳转规则、统一动画。 - 需要 DeepLink / 应用内链接跳转
推送跳转、网页唤起指定页面,Navigation 原生支持。 - 配合 Jetpack 架构(ViewModel、Hilt 等)
官方推荐组合,生命周期完全对齐。 - 单 Activity 多 Fragment 架构
这是 Google 现在主推的架构,Navigation 是官方标准方案。
简单总结
- 小项目/简单页面:用 FragmentTransaction 没问题。
- 中大型项目/标准架构:必须用 Navigation 组件,减少 80% 导航相关 Bug。
2:如何设计合理的导航结构?遵循哪些原则?
一、导航结构设计步骤
- 梳理页面层级
划分:首页 -> 二级页面 -> 详情页 -> 弹窗/对话框。 - 绘制导航图(Navigation Graph)
一个主图 + 多个子图(按模块拆分:用户、订单、商城)。 - 定义入口与出口
明确哪个是起始目的地、哪些页面是全局可访问的。 - 规划回退栈行为
哪些页面跳转需要清空回退栈(如登录 → 首页)。
哪些页面需要保留回退栈(如列表 → 详情)。
二、必须遵守的导航设计原则
- 单 Activity 架构原则
整个应用只留一个 MainActivity,所有页面都是 Fragment。 - 导航中心化原则
所有跳转规则只在导航图中定义,不分散在代码里。 - 类型安全原则
必须使用 Safe Args 传递参数,禁止裸写 Bundle。 - 回退栈可预测原则
用户按返回键,必须符合预期,不乱跳、不崩溃。 - 解耦原则
Fragment 之间不互相引用,只通过导航组件通信。 - 嵌套导航原则
首页底部导航栏,每个 Tab 对应一个嵌套导航图,互不干扰。 - 全局通用页面独立原则
网页、登录、设置等全局页面,抽成包含式导航图(include)。
优秀导航结构示例
主导航图 ├── 首页嵌套图 (Home) ├── 发现嵌套图 (Discover) ├── 我的嵌套图 (Profile) ├── 全局页面 (登录、WebView、设置) └── 弹窗/对话框 (DialogFragment)3:Navigation 如何与 ViewModel、LiveData 配合?
这是 Jetpack 架构的黄金组合
一、核心配合机制
ViewModel 作用域
- Navigation 管理的 Fragment,可以共享同一个 ViewModel
- 作用域 =导航图范围(NavGraph)
→ 实现同模块页面之间数据共享,不跨页面污染。
LiveData 负责数据驱动
ViewModel 持有数据,Fragment 观察数据变化,自动更新 UI。生命周期完全对齐
Navigation 自动管理 Fragment 生命周期 → ViewModel 自动创建/销毁。
二、实战用法(代码示例)
1. 共享 ViewModel(同导航图内的 Fragment 共享数据)
// 1. 定义共享 ViewModelclassSharedViewModel:ViewModel(){valuserLiveData=MutableLiveData<User>()}// 2. Fragment 中获取(导航图作用域)classHomeFragment:Fragment(){// 通过 currentBackStackEntry 获取 【当前导航图范围的 ViewModel】privatevalviewModel:SharedViewModelbynavGraphViewModels(R.id.nav_home)// 观察数据viewModel.userLiveData.observe(viewLifecycleOwner){user->tvName.text=user.name}}// 另一个 Fragment 也用同一个 ViewModelclassDetailFragment:Fragment(){privatevalviewModel:SharedViewModelbynavGraphViewModels(R.id.nav_home)}2. 跳转时传递数据(Safe Args + ViewModel)
// 1. 在导航图中定义参数<argument android:name="userId"app:argType="long"/>// 2. 跳转时传递findNavController().navigate(HomeFragmentDirections.actionHomeToDetail(userId))// 3. 接收页面获取参数valargs:DetailFragmentArgsbynavArgs()valuserId=args.userId3. 跳转后回传数据(新版 Navigation 方式)
// A 页面跳转并监听返回结果findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")?.observe(viewLifecycleOwner){result->// 收到 B 页面回传的数据}findNavController().navigate(...)// B 页面返回时设置数据findNavController().previousBackStackEntry?.savedStateHandle?.set("key","我是返回数据")findNavController().popBackStack()三、三者配合的优势
- 页面无耦合:Fragment 不互相引用
- 数据安全:屏幕旋转、配置变更,数据不丢失
- 生命周期安全:不会发生内存泄漏
- 代码简洁:减少大量样板代码
- 可测试性强:ViewModel 可单元测试
最终总结
- Navigation 优势:自动管理回退栈、类型安全、可视化、支持 DeepLink,适合单 Activity 架构。
- 导航设计原则:中心化、单 Activity、嵌套导航、作用域隔离、回退栈可预测。
- 与 Jetpack 配合:
navGraphViewModels()实现导航图内共享 ViewModel- LiveData 做数据驱动
- Safe Args 做安全参数传递
- SavedStateHandle 做页面间回调
这就是 Google 官方推荐的现代化 Android 导航架构。