Nav3 示例集:面向 Jetpack Navigation 3 的实用导航用例与模式
Nav3 官方示例仓库,提供模块化、可复用的导航用例与模式,适合作为迁移、集成与学习 Jetpack Navigation 3 的参考
💡 深度解析
3
项目如何保证导航状态在配置变更和进程死亡时持久化与恢复?在迁移到生产时需要注意哪些实现细节?
核心分析¶
问题核心:如何在配置变更和进程死亡后可靠恢复导航栈与 UI 状态?仓库通过 saveable back stack 示例给出实现模式,但迁移到生产需谨慎处理序列化与版本问题。
技术分析¶
- saveable back stack:利用 Nav3 的持久化能力让 back stack 在系统恢复时重建。
- SavedStateHandle:在 ViewModel 层保存关键状态,确保在重建后还能恢复 UI。
- 合成栈与初始化顺序:重建合成返回栈时需要按原始入栈顺序恢复,以保证历史一致性。
- 数据可序列化性:所有保存到 back stack 或 SavedStateHandle 的字段必须可通过 Bundle/Parcel(或自定义序列化)存储。
实用建议¶
- 锁定依赖版本:示例可能使用 alpha/snapshot,生产应锁定稳定版本或评估版本变更成本。
- 审查序列化边界:避免将大型对象、Context、callback 等放入保存状态;使用 ID/引用并在重建时重新加载。
- 覆盖恢复测试:编写进程死亡与配置变更的集成测试,验证 restore 行为与 UI 一致性。
- 记录入栈策略:明确哪些 entry 是合成生成的,并在重建时复用同一策略以避免重复入栈。
重要提示:未序列化的数据或 API 变动是导致恢复失败的主要风险源,务必在移植前做全面检查与测试。
总结:仓库提供的 saveable back stack 示例是实现恢复的良好蓝图,但生产采用时需关注序列化、版本锁定与恢复测试,确保鲁棒性。
仓库如何实现从 Intent 解析 deep link 并重建合成返回栈(synthetic back stack)以保证 Up/Back 行为一致?
核心分析¶
问题核心:Deep link 直接打开深层目的地时,用户期望按 Up/Back 能返回到合理的上层页面。仓库的 advanced 示例通过“合成返回栈”来解决该问题。
技术分析¶
- 解析流程:先从
Intent中解析 deep link URL,映射为导航 key(或目的地标识)。 - 生成入栈序列:把目标转换为一系列逻辑 entry(例如:Home -> List -> Detail),这些 entry 按顺序写入导航栈以重建历史。
- 恢复与持久化:结合
saveable back stack和初始化时的入栈逻辑,可在配置变更或进程死亡后恢复合成栈。 - Edge cases:需避免重复入栈、处理单例目的地(singleTop 行为),并确保 ViewModel 的作用域与 entry 生命周期一致。
实用建议¶
- 先复现示例:在独立 recipe 中运行 deep link 示例,观察入栈顺序与 Up 行为。
- 定义映射规则:明确 URL -> navigation key -> entry 列表的映射规则并在路由层集中管理。
- 添加防重入逻辑:对多次接收相同 deep link 的情形,加防重入检查(或利用导航的 singleTop semantics)。
重要提示:若直接复制示例代码到生产,请审查 ViewModel 作用域与入栈时机,错误的时机会导致 UI/状态不一致或重复请求。
总结:项目给出了从 Intent 到合成返回栈的端到端示例,是处理 deep link 场景的实用参考,但需要结合 App 的生命周期/作用域策略审慎移植。
在仓库中,如何在不同 ViewModel 构造方式(viewModel(), hiltViewModel(), koinViewModel())下安全地传递导航参数并返回结果?
核心分析¶
问题核心:在不同的 ViewModel 构造方式下,如何确保导航参数正确注入且返回结果可被接收,且不会引发生命周期/作用域问题?
技术分析¶
- 参数传递:把导航参数作为 entry 的属性或 navigation key 显式声明,ViewModel 在构造时从 entry 或 SavedStateHandle 中读取。
- DI 与作用域对齐:
viewModel(): 默认与 Composable/Activity 的NavBackStackEntry作用域相关联。hiltViewModel(): 需确保 Hilt 的导航组件或 Activity component 与 entry 的作用域匹配,避免跨 entry 复用错误的实例。koinViewModel(): 类似地,需要配置正确的 Koin scope 并在 navigation module 中声明。- 结果返回模式:
- 事件式:用一次性通道(
SharedFlow/事件回调)返回结果,适合短期交互。 - 状态式:把结果写入 CompositionLocal / SavedStateHandle,使目标在被复用或恢复时可读取。
实用建议¶
- 先用 SavedStateHandle 显式保存参数,避免直接依赖构造函数注入未对齐的 scope。
- 统一作用域策略:在模块化/DI 场景中,明确每个导航 entry 的 DI scope,并在示例基础上实现相同策略。
- 为返回结果选择幂等方案:事件式适合一次性操作,状态式适合需要在恢复后持久化的结果。
重要提示:错误的作用域对齐是常见坑,会导致参数为空、ViewModel 被复用或泄露。
总结:仓库展示了三种构造方式下的参数注入与两种结果返回范式。移植时以作用域一致性和 SavedStateHandle 为基础,可显著降低问题发生概率。
✨ 核心亮点
-
官方维护的 Nav3 示例,覆盖关键导航用例与模式
-
模块化示例便于学习、复用与集成到项目中
-
部分示例使用 Nav3 快照/alpha 版本,可能随 API 变动而失效
-
贡献者与提交活动极少,长期维护与社区支持存在不确定性
🔧 工程化
-
官方示例集,覆盖 Nav3 常见导航场景与实现
-
示例涵盖深度链接、场景布局、动画与多返回栈等用例
-
提供与 Hilt、Koin、ViewModel 与 Compose 的集成示例
⚠️ 风险
-
仓库无发布且提交/贡献数据极低,存在维护与同步风险
-
部分示例依赖 Nav3 快照或 alpha,API 变动会导致示例失效或需频繁更新
👥 适合谁?
-
Android 开发者,尤其是迁移到或采用 Jetpack Navigation 3 的团队
-
架构工程师与样例消费者,用于学习模式、集成方案与最佳实践