HarmonyOS API 26 Navigation 跨包路由:router_map、HSP 按需加载与失败回落

模块化应用不能把跨包跳转理解成"换一个字符串"。页面名称、模块边界、router_map、按需加载、错误恢复和路由栈所有权必须形成同一条可验证链路。

一、跨包路由解决什么问题

随着功能拆入 HAP、HSP 或 HAR,入口模块不应直接依赖每个页面组件。系统路由表把页面名称映射到来源文件和 Builder,调用方通过 NavPathStack 提交名称,由平台完成模块定位、组件构建和页面跳转。

解耦并不代表无需契约。名称冲突、模块未安装、下载失败、Builder 不匹配仍需要应用侧治理。

二、官方能力边界

华为跨包路由指南说明,Navigation 提供系统路由表和自定义路由表;从 API 12 起可用系统路由表实现动态路由,各业务模块可以独立配置 router_map.json。官方资料还指出,从 API 23 起支持跳转按需加载的 HSP 页面。

具体模块类型、打包约束、字段定义和设备支持以目标 API 26 文档及工程模板为准。

三、router_map的三个核心字段

常见映射包含页面唯一名称、页面源码路径和对外 Builder 名称。字段必须与文件、导出函数和模块资源一致。

json 复制代码
{
  "name": "orders/OrderDetail",
  "pageSourceFile": "src/main/ets/pages/OrderDetail.ets",
  "buildFunction": "OrderDetailBuilder"
}

这段是结构示意,不代表已在真实工程验证。

四、module.json5必须注册路由表

创建 profile 文件不等于平台会读取它,还要在对应模块配置中引用。路径、资源名和模块边界错误都会导致运行时找不到目标。

json5 复制代码
{
  module: {
    routerMap: "$profile:router_map"
  }
}

修改后需要真实 HarmonyOS 构建才能确认语法和资源解析。

五、页面名称采用命名空间

多个业务包都叫 Detail 时容易冲突。建议使用稳定命名空间,例如 orders/OrderDetail、account/Profile,并把名称集中到公共契约模块。名称是路由身份,不应随中文标题或运营文案变化。

六、契约模块只放类型和常量

公共模块可以暴露路由名、参数 DTO 与结果类型,但不要反向依赖具体页面实现。Product 依赖功能契约,Feature 实现 Builder,依赖方向保持清晰。

ts 复制代码
export const OrderRoutes = { detail: 'orders/OrderDetail' } as const

七、参数必须跨包可理解

调用方和目标包可能独立演进。参数使用小型、显式、版本化 DTO,避免传页面实例、Context、函数或大对象。稳定业务 ID、来源枚举和 schemaVersion 通常足够。

八、Builder是页面构建边界

router_map 中的 buildFunction 必须对应可访问的实例化方法,且最终构建有效 NavDestination。名称正确但 Builder 未导出、签名不匹配或未产生目标节点,仍会跳转失败。

九、系统路由表不等于网络下载

已随包安装的模块与按需 HSP 是不同准备状态。普通跨包解析不必假设联网;按需加载则可能受网络、空间、版本和签名影响。文章与代码必须明确具体场景。

十、按需HSP先做模块准备

对需要下载的目标,模块准备成功和页面入栈是两个检查点。ModuleService 确认网络条件、请求模块并验证可用性;之后 RouteCoordinator 再调用 NavPathStack。不要在下载过程中连续 push 同一页面。

十一、重复请求按模块和页面合并

多个入口同时请求同一按需页面时,下载任务应按 moduleId 合并,路由任务再按 requestKey 合并。模块共享不代表页面实例共享,两层去重要分别设计。

ts 复制代码
const moduleTask = modulePending.getOrCreate(moduleId, prepareModule)
await moduleTask
return routePending.getOrCreate(requestKey, pushTarget)

十二、离线场景要提前判断

如果模块尚未准备且设备离线,立即进入可解释回落,不要让用户长时间等待。若模块已经可用,离线不应阻断本地页面跳转。策略不能简单写成"无网禁止所有跨包路由"。

十三、失败回落必须保留上下文

目标不可用时默认保留来源页,并提供重试、返回主页或打开已安装替代页面。不要 clear 全栈,也不要跳转到另一个同样依赖缺失模块的错误页。

十四、区分模块错误与路由错误

模块下载失败、校验失败、Builder 未注册、NavDestination 不存在和参数错误是不同阶段。统一提示可以简洁,但诊断事件必须保留阶段和受控错误码,才能定位根因。

十五、路由表构建检查应前置

CI 或本地脚本可以检查名称唯一、文件路径存在、Builder 名称非空、契约常量覆盖和重复 namespace。静态检查不能替代 hvigor 构建,但能在运行前发现大量配置错误。

十六、跨包路由仍遵守栈所有权

页面来自另一个 HSP,不代表应该操作另一个 Navigation。请求必须交给当前容器拥有的 NavPathStack;父子栈场景由上层协调器选择正确 owner。禁止功能包获取全局控制器任意跳转。

十七、每个Navigation仍是一栈一对象

官方页面路由指南强调 NavPathStack 与 Navigation 一一对应、不可复用。模块化项目尤其容易把一个全局栈注入所有页面,最终导致工作区、弹窗流和详情流相互污染。

十八、动态入口需要权限复核

按需模块准备完成时,用户登录态和权限可能已经变化。入栈前重新检查 owner generation、账号代次和业务授权。模块下载成功只是资源可用,不是访问授权。

十九、迟到下载不能强制跳转

用户等待时可能离开页面或切换账号。下载完成回调先比对 request owner;已失效就只缓存模块可用状态,不自动把目标页面推到当前栈顶。

二十、升级时治理参数版本

入口模块与 HSP 可能分批升级。DTO 携带 schemaVersion,目标模块只接受兼容范围;不兼容时进入安全错误态。不要根据字段"看起来存在"就继续运行。

二十一、路由名称不能随模块重构漂移

移动源码文件时可以更新 pageSourceFile,但稳定页面名应尽量保留。确需改名时提供显式迁移表,恢复数据和深链先转换旧名称,再提交新目标。

二十二、恢复栈要过滤缺失模块

持久化恢复前检查每个页面名称是否仍注册、参数版本是否兼容、目标模块是否可用。缺失按需模块不要在冷启动时静默下载并阻塞首屏,可先恢复安全主页,再由用户明确触发。

二十三、深链映射不能直通router_map

外部 URL 路径先经过域名、路径、参数白名单和登录态校验,再映射到本地路由名。攻击者提供的任意 name 不能直接传给 NavPathStack。

二十四、HAR与HSP的职责要区分

HAR 常用于共享代码与资源,HSP 可承载共享业务能力,HAP 是应用包模块。具体页面是否能作为动态目标取决于工程形态和官方支持,不应仅凭目录名称推断运行能力。

二十五、预览器结果不能代表系统路由表

官方跨包资料指出系统路由表支持模拟器但不支持预览器。预览器能显示页面组件,不代表 router_map、跨包加载或真实路由过程已经验证。验收需要模拟器或设备以及真实构建产物。

二十六、可观测字段要脱敏

记录 routeAlias、moduleAlias、准备阶段、耗时、来源枚举和结果;不记录完整深链、业务对象、令牌或用户内容。下载和路由事件用同一 operationId 关联,但对外上报采用受控散列。

二十七、无障碍和布局仍由页面负责

跨包成功只说明目标被构建并入栈。标题、返回按钮、焦点、深浅色、横竖屏、分栏和加载态需要目标模块独立验收。按需下载进度也应提供可读文本,不能只显示无标签动画。

二十八、纯策略模型的范围

配套 CrossPackageRoutePolicy.ts 按空名称、栈所有权、注册状态、模块准备和网络条件裁决允许、准备模块或拒绝。32项主机测试覆盖优先级、离线已安装和离线缺失。

模型不解析 router_map、不下载 HSP、不实例化 NavPathStack,也不证明系统跨包跳转成功。

二十九、静态检查示例

ts 复制代码
interface RouteMapEntry { name:string; pageSourceFile:string; buildFunction:string }
function assertUnique(entries: RouteMapEntry[]): void {
  const names = new Set<string>()
  for (const entry of entries) {
    if (names.has(entry.name)) throw new Error(`duplicate route: ${entry.name}`)
    names.add(entry.name)
  }
}

真实脚本还要验证路径、模块契约和 JSON 格式。

三十、真实工程验收矩阵

  • 同包、跨 HAP/HSP/HAR 的允许路径;
  • 名称冲突、路径错误和 Builder 缺失;
  • 已安装模块离线跳转;
  • 按需模块在线成功、离线失败和下载中断;
  • 重复下载与重复入栈合并;
  • 下载期间离场和切换账号;
  • 恢复数据包含旧名称或缺失模块;
  • 父子 NavPathStack 所有权;
  • 模拟器与真机运行;
  • 焦点、返回、多设备和深浅色。

三十一、常见问题排查

现象 常见原因 处理
目标页空白 Builder 或根节点不正确 核对导出和NavDestination
找不到页面 router_map未注册或名称漂移 对照模块配置与契约
离线已安装页也被拦截 把联网当统一前置条件 区分模块准备状态
下载完成突然跳页 未校验迟到owner 只缓存模块状态
两个容器串栈 全局复用NavPathStack 一容器一栈

三十二、官方边界与验证声明

三十三、三十二点一、模块卸载与缓存失效要可恢复

按需模块曾经准备成功,不代表以后始终存在。用户清理空间、版本升级或安装状态变化后,本地"已就绪"缓存可能过期。每次关键跳转都要通过模块服务获取当前可用性,而不是永久相信一个布尔值;检测到失效时清理缓存并重新进入准备或回落流程。

恢复栈中如果包含已卸载模块,应用先保留安全主页和可用页面,再向用户解释缺失功能。不能为了复原历史栈强制下载,也不能让一个缺失页面阻断整个首屏。模块重新可用后,由用户明确操作进入目标,避免迟到恢复改变当前上下文。

三十四、三十二点二、路由契约变更需要兼容窗口

跨包独立演进时,调用方可能先于目标模块升级。新增参数应保持可选并有默认语义,删除或改名字段要提供迁移窗口。目标模块遇到更高版本 DTO 时应拒绝并回落,而不是忽略未知字段后执行可能错误的业务。

契约版本、模块版本和路由表版本应进入脱敏诊断事件。只有构建、安装和跨版本组合测试通过,才能缩短兼容窗口或移除旧映射。

华为官方跨包路由与页面路由资料说明了系统/自定义路由表、各模块 router_map 配置、NavPathStack 路由调用、API 23 起按需 HSP 页面支持及模拟器/预览器边界。具体能力以目标 SDK 文档为准。

本文未执行 HarmonyOS API 26 工程编译、router_map 系统解析、HSP 下载、跨包 Builder 构建、ArkUI 联调、模拟器或真机验收,不把32项主机策略测试描述成平台结果。

三十五、总结

跨包路由的可靠链路是:稳定名称与版本化参数形成契约,router_map 完成模块映射,ModuleService 管准备,RouteCoordinator 管所有权和去重,NavPathStack 管真实入栈,失败回落保留来源上下文。只有把下载和路由分成两个检查点,模块化才能既解耦又可诊断。

三十六、AI辅助声明

三十七、接入前检查清单

HarmonyOS AP正式接入前,工程侧要过一遍检查清单:SDK 版本与目标 API 版本匹配、权限在清单中声明且按需申请、能力开关在专用配置层管理、包体积增量符合预算。任何一项不过就先停,带着不匹配的版本往上冲,排错成本会翻倍。

ts 复制代码
interface PrecheckItem { name: string; pass: boolean; note?: string }
const checklist: PrecheckItem[] = [
  { name: 'SDK/API版本匹配', pass: false },
  { name: '权限声明完整', pass: false },
  { name: '开关集中管理', pass: false },
  { name: '包体积增量<预算', pass: false },
]
const allPass = checklist.every(x => x.pass)

检查清单跑通的标志是:新建工程按清单接入一次成功,且不依赖任何口头经验。做不到,说明文档还缺关键步骤。

三十八、常见坑与版本适配记录

HarmonyOS AP最常踩的坑集中在三处:示例代码用的旧接口在新版本被拆分、默认配置与生产预期不一致、调试环境与真机行为有差异。每踩一个坑就记进版本适配表,注明坑点、影响版本、修复方式与验证方式。

ts 复制代码
interface Pitfall { issue: string; sinceApi: string; fix: string; verifiedOn: string[] }
const pitfalls: Pitfall[] = []
function knownPit(api: string): Pitfall[] { return pitfalls.filter(p => p.sinceApi === api) }

适配表的价值在升级时兑现:每次目标版本变更,先对照表过一遍已知坑,能省下一整轮盲目排查。

相关推荐
KevinChaos12 分钟前
阳台小花园开发手记 04|HarmonyOS 7.0 互动卡片:倾斜手机时的卡片效果
华为·harmonyos
威哥爱编程4 小时前
模拟面试智能体开发实战 04:面试聊到哪算哪?用状态机把整场面试编排起来
python·agent·harmonyos
威哥爱编程5 小时前
模拟面试智能体开发实战 03:AI 面试官太客气?人设 Prompt 让它像个真考官
python·agent·harmonyos
贾伟康9 小时前
HarmonyOS API 26 Navigation 导航栏位置:navBarPosition、左右布局与折叠屏适配
harmonyos·arkts·arkui·navigation·折叠屏
贾伟康1 天前
HarmonyOS API 26 DevEco Code 需求到 ArkTS 骨架的提示词分层
harmonyos·arkts·ai coding·deveco code·工程提效
威哥爱编程1 天前
模拟面试智能体开发实战 02:回答等半分钟,谁还愿意练?把服务端和流式输出搭起来
python·agent·harmonyos
威哥爱编程1 天前
模拟面试智能体开发实战 01:面试挂了都不知道挂在哪?用 Python 给自己造一个随叫随到的 AI 面试官
python·agent·harmonyos
贾伟康1 天前
HarmonyOS API 26 HMAF Skill 可解释任务计划与失败回退
harmonyos·arkts·智能体·skill·hmaf
贾伟康1 天前
HarmonyOS API 26 HMAF 2.0 意图解析的可解释动作图
harmonyos·arkts·智能体·a2a·hmaf