跳到主要内容

配置可上线的导航宿主

请先完成导航教程,再使用本指南。教程里的双目标页示例会在这里 扩展为一套明确约束恢复、返回键、所有权与失败策略的宿主。规则背后的运行时原因见 导航运行时架构。Motion、深链、多栈、Graph Owner 和自适应 Pane 的完整签名与可选 API 仍由 Navigation Android 模块手册 维护。

选择唯一的 Controller Owner​

在挂载 NavHost 的同一个 UI Owner 中通过 rememberNavHostController 创建 Controller。 不得缓存在进程单例或跨 Host 共享。它通过最近的 ViewCompose Registry 保存已提交栈与 Owner Identity、参数和 Destination State。

请把 NavHost 挂在 LocalLifecycleOwner 和 LocalViewModelStoreOwner 两个边界之下。标准 Activity 与 Fragment setUiContent Host 会提供二者;renderInto 集成必须显式提供,因为没有私有兜底 Store。

当 Route 需要类型化参数、嵌套所有权或深链时,请使用稳定的 NavGraph。如果当前 Graph 已不 接受保存的 Route 层级,恢复会失败关闭到起始目标页。

为每个应用 Route 声明一个稳定 NavRouteSpec<T>,并在 destination、navigation、Controller 类型化命令与 NavEntry.toRoute 中复用。只编码持久 ID 和少量基础值,领域对象由 ViewModel 加载,并保持 Name 与 Schema 可恢复。Codec 错误发生在 Host 事务前。

可选 Kotlinx Adapter 为扁平序列化 Route 派生 Spec;不支持的 Shape 使用显式 Core Codec。

使用 NavDeepLinkRequest 表达外部导航。声明可以约束 URI、action、MIME type 或三者组合,且 每项约束都必须匹配。Android 只映射 Intent Data、Action 与 Type。检查 NavDeepLinkResult,并在 安全边界验证完整 URI。

恢复状态并接入平台返回​

保持 systemBackEnabled = true。处于 STARTED 且可 Pop 时,NavHost 使用最近的 View-tree NavigationEvent Owner,仅在不存在时回退 Activity Back。根节点向外委派;不要再包第二个 Owner 或 Callback。

界面内返回按钮调用 popBackStack。系统返回和 Predictive Back 就会使用同一事务边界。 Predictive Preview 不发布候选栈;取消恢复已提交 Scene,完成走程序化 Pop 路径。

声明稳定的 NavResultKey,带值 Pop,并在上一页用 NavResultEffect 观察。交付可保存、遵循 FIFO,并等待页面 RESUMED;显式确认或重试使用 Destination Context Inbox。

穷举处理 Route 渲染​

在 NavHost 内容块中渲染每个可接受 Route,并立即拒绝未知 Route。内容块运行在 Destination 自有的 Lifecycle、Store、Saveable Namespace 与子 RenderSession 中;除非 Launch Mode 复用, 重复 Push 会创建不同 Owner。Scoped Store 随 Parent 跨配置重建存活,在永久移除时清理,并在进程 重建后从状态创建新 ViewModel。只为不可观察的父级 Capture 修改 contentKey;Host Owner、 Controller、Factory、调试身份或 Host key 改变会重建原生 Host。

观察 Destination Presentation,而不复制 Lifecycle​

当内容需要区分 Hidden、Visible、Covered、Interactive、Transition、Pane 或 Overlay Role 时, 应在 Destination DSL 声明阶段读取 LocalNavDestinationContext.current,并为回调捕获最近 Holder。 其 Entry 跨隐藏展示释放存活;永久移除会停止更新并销毁 Lifecycle。活动资源仍遵循 AndroidX Lifecycle,因为该 Context 只表达粗粒度 Role,不含逐帧 Progress。

添加模态 Destination,而不建立第二套 Lifecycle 模型​

向 NavHost 传入稳定的 NavSceneStrategies.trailingOverlays。 Predicate 只选择 Stack 末尾后缀,Pane Policy 布局其前缀。Destination 内容绘制 Surface/Scrim, Host 负责模态输入与 Lifecycle。继续使用普通 Back、Result、Restore 与 Predictive API。

明确选择展示保留策略​

除非针对具体 Destination 的真机证据表明其原生 View Tree 重建成本不可接受,否则保持默认 DisposeWhenHidden。它释放隐藏原生展示但保留 Owner State。需要时使用经测量的 Bounded(n); RetainAll 无界。策略变化保留 Owner,首次或恢复连接只物化当前 Scene Layout。

自定义集成只保留一个策略来源​

普通应用使用 NavHost。自定义 Host 必须完整执行 NavExecutionPlan:Commit 前准备,一起发布 Scene/Lifecycle/Interaction/Back,再按计划清理;不得派生并行 Lifecycle、Retention 或 Back Policy。

处理命令结果​

每个命令返回 Committed、NoChange、Queued 或 Failed。通过 navigationState 观察入队任务 完成,并上报结构化 Failure,不替换已提交栈。日志、降级或测试使用 onFailure,否则抛出 NavHostException。提交前失败保留旧页面,NavFailure.stackCommitted 标记提交后边界。

验证任务​

运行编译教程和 Navigation Android 测试:

./gradlew :samples:tutorials:assembleDebug :viewcompose-navigation-android:testDebugUnitTest

在一条真实 Host 路径中验证:界面与系统 Back 一致;Activity 重建保留 Route、Entry、可保存状态 和 ViewModel Identity;Predictive Back 取消与提交分别改变栈零次与一次;提交前渲染失败保留前页; 深栈展示符合策略,且被淘汰页面恢复 Owner 状态。Detached 命令、重复 Pop、Owner 提前清理、无界 原生保留,或把 Queued 当成完成,都表示配置失败。