HarmonyOS应用实战-启示散页-47-HSP 功能页别自己注册路由:让宿主统一掌握入口表

HarmonyOS应用实战-启示散页-47-HSP 功能页别自己注册路由:让宿主统一掌握入口表

HSP 里新增一个页面后,最省事的做法是功能包自己写路由名、自己跳过去。短期能跑,长期会让宿主不知道实际暴露了哪些入口;拆包、灰度、下线和权限拦截时,路由治理点散落在多个模块里。

在这里插入图片描述

这篇文章解决四件事:

  1. 还原这个问题在答案之书这类离线应用里如何出现。
  2. 明确页面、Service、Repository、AppStorage 或发布清单各自的责任。
  3. 给出可迁移的 ArkTS/工程代码片段,并说明反例为什么会留下隐患。
  4. 用验证清单和排障表把方案收成可执行检查项。

在这里插入图片描述
在这里插入图片描述

功能页可以来自 HSP,入口权不能交给 HSP

HSP 适合承载可复用功能页,但宿主必须知道哪些页面可以被打开、从哪里打开、用什么参数打开。如果 HSP 自己硬编码宿主路由名,就会形成反向依赖:功能包知道宿主入口,宿主反而不知道功能包暴露了什么。

已核对的实现是:libraryHSP/Index.ets 导出页面、组件和服务,entry 的 Index.ets 集中维护 Navigation 的 pageMap。本文的 HostRouteRegistry 是围绕这个现状提出的治理设计。

路由责任拆成导出、登记、跳转三步

先写 owner 表,再写代码。否则代码能跑起来,却很难说明失败时该由谁回滚、重启后该由谁恢复、其他页面该根据什么信号刷新。

Owner负责什么不负责什么
libraryHSP/Index.ets导出页面 Builder 和服务能力决定宿主入口是否可见
libraryHAR/Routes.ets保存稳定 RouteName 常量引入 ArkUI 页面实现
entry HostRouteRegistry登记入口、参数约束、灰度和拦截规则把业务页面写进 HSP
Navigation pageMap按宿主路由表分发 Builder到处散写 if/else

RouteRecord 让入口表可审计

模型要表达本链路需要的稳定事实,不要把页面临时状态或底层存储细节暴露出去。这样后续迁移 Preferences schema、拆模块或增加发布检查时,调用方不必跟着重写。

type RouteName = 'Home' | 'DeckEdit' | 'Drawing' | 'ReleaseCheck';

interface HostRouteRecord {
  name: RouteName;
  ownerModule: 'entry' | 'libraryHSP';
  requiresDeckId: boolean;
  enabled: boolean;
}

这段模型的重点有三点:字段命名贴近业务;输入输出能覆盖失败分支;没有携带 ArkUI 组件状态。页面拿它展示,Service 拿它做判断,Repository 不需要知道页面长什么样。

宿主登记入口并做参数约束

Service 是规则 owner。凡是涉及校验、回滚、冲突、恢复、隐私或发布证据的逻辑,都不要散落在组件回调里。

class HostRouteRegistry {
  private records: HostRouteRecord[] = [
    { name: 'DeckEdit', ownerModule: 'libraryHSP', requiresDeckId: true, enabled: true },
    { name: 'Drawing', ownerModule: 'libraryHSP', requiresDeckId: true, enabled: true },
    { name: 'ReleaseCheck', ownerModule: 'entry', requiresDeckId: false, enabled: false }
  ];

  resolve(name: RouteName, params: Record<string, string>): HostRouteRecord {
    const record = this.records.find((item) => item.name === name && item.enabled);
    if (!record) {
      throw new Error(`入口未开放:${name}`);
    }
    if (record.requiresDeckId && !params.deckId) {
      throw new Error(`入口缺少 deckId:${name}`);
    }
    return record;
  }
}

这里的 Service 不追求复杂抽象,只做一件事:把输入转成可解释结果。页面可以做乐观交互,但最终事实必须从 Service 返回。

HAR 只放路由常量,不反向依赖 UI

Repository 负责稳定读写、默认值和 schema 兼容。它不弹 Toast,不决定按钮状态,也不拼页面文案。

export const BookRoutes = {
  Home: 'Home',
  DeckEdit: 'DeckEdit',
  Drawing: 'Drawing',
  ReleaseCheck: 'ReleaseCheck'
} as const;

export type BookRouteName = typeof BookRoutes[keyof typeof BookRoutes];

如果这一层缺失,页面会被迫知道 store name、key、默认值和异常处理细节。写到后面,所有页面都会变成半个仓储层。

entry 的 pageMap 是唯一分发点

页面只消费结果、展示状态、触发动作。跨页面刷新用轻量信号,完整业务对象继续由 Service 重新读取。

@Builder
function pageMap(name: string, param: object) {
  if (name === BookRoutes.DeckEdit) {
    DeckEditPageBuilder(param);
  } else if (name === BookRoutes.Drawing) {
    DrawingPageBuilder(param);
  } else if (name === BookRoutes.ReleaseCheck) {
    ReleaseChecklistPageBuilder(param);
  }
}

Navigation(this.pathStack) {
  HomePage()
}.navDestination(pageMap)

这类写法的好处是:入口可以扩展,页面可以重进,数据可以迁移。只要 Service 和 Repository 边界稳定,页面不需要关心底层怎么保存。

反例:短期省事,长期失控

反例是在 HSP 页面内部直接 pathStack.pushPath({ name: 'SomeHostPage' }),并把宿主路由名写死。这样 HSP 和 entry 互相知道内部细节,功能下线时必须跨模块搜索所有跳转点。

更具体地说,反例通常有三个共同点:直接写持久化、没有失败结果、没有刷新 owner。它们在单次手测里很难暴露,但在重启、返回、跨入口或发布复查时会变成真实问题。

排查顺序:\n1. 先找唯一写入 owner。\n2. 再看失败是否返回可展示结果。\n3. 再看刷新信号是否只通知相关页面。\n4. 最后才检查 UI 展示。

验证路径不要只走正常操作

  • 扫描 HSP,确认没有硬编码宿主专属路由名。
  • 移除一个 HSP 导出时,宿主入口表能集中暴露编译或启动期问题。
  • 缺 deckId 进入 DeckEdit/Drawing 时被 registry 拦下,而不是到页面里才崩。
  • 新增 ReleaseCheck 入口时只改宿主入口表和 pageMap。

验证时建议把“正常路径、异常输入、重启恢复、跨入口刷新、发布态检查”分开记录。构建通过只能证明语法和资源能打包,不能证明这些运行链路都已经被真机验证。

rg -n "PreferencesStore|AppStorage.setOrCreate|Repository|Service" D:\\ProgramData\\huawei\\lesson\\The_Book_of_Answers\nrg -n "question|answerText|deckName|hilog" D:\\ProgramData\\huawei\\lesson\\The_Book_of_Answers

常见问题与处理

现象先看哪里处理
点击入口无反应registry 是否 enabled先看 HostRouteRecord
HSP 拆包后路由找不到宿主是否登记 Builderentry 统一维护 pageMap
参数到页面才报错requiresDeckId 是否提前校验入口层拦截无效参数

处理这些问题时不要先改 UI 文案。先确认写入 owner、读取 owner 和刷新信号是否一致,再看页面是否正确消费结果。若只在页面补一个 Toast,用户当次可能看到了提示,但重启、返回、跨入口和发布复查仍然会暴露同一个根因。

落地取舍

这套方案不是为了把轻量应用写重,而是为了把真正会跨页面、跨启动、跨发布阶段的事实收住。只影响当前展示节奏的变量可以留在页面;会改变用户内容、持久结构、隐私口径或发布证据的逻辑,必须进入 Service、Repository 或发布清单。

判断点建议位置原因
只影响当前按钮、弹层或动画页面 @State不需要跨入口复用
会写本地数据或读持久事实Service + Repository需要校验、回滚和恢复
会影响其他页面刷新AppStorage 时间戳通知变化,不共享完整对象
会影响发布、截图、隐私或诊断发布清单或运行账本后续复查需要证据

真正落地时,可以先从一条最容易复现的路径开始:找出唯一写入点,补上结果模型,再把页面里的直接读写替换成 Service 调用。这个顺序比一次性重构全部页面更稳,也更容易在评审时说明每一行代码解决了哪个故障链。评审记录里最好保留对应的命令、截图或复现步骤,避免方案只停留在口头约定。

小结

HSP 可以提供页面,但入口治理属于宿主。把 RouteName 放在公共层,把 Builder 导出放在 HSP,把入口登记放在 entry,路由链路就能被审计、灰度和下线,而不是靠跨模块搜索碰运气。
说明每一行代码解决了哪个故障链。评审记录里最好保留对应的命令、截图或复现步骤,避免方案只停留在口头约定。

小结

HSP 可以提供页面,但入口治理属于宿主。把 RouteName 放在公共层,把 Builder 导出放在 HSP,把入口登记放在 entry,路由链路就能被审计、灰度和下线,而不是靠跨模块搜索碰运气。

内容概要:本文基于某互联网公司2025年约142万元的SEM广告投放数据,构建了“诊断—分类—优化—鲁棒决策”四层次建模框架,系统性提升广告投放效益。研究从广告创意、关键词管理、出价与预算、投放时间四个维度开展策略合理性诊断,揭示了工作日效益高、节假日期效波动剧烈等时间规律,并识别出预算过度集中于少数方案的结构性风险。针对关键词,提出基于成本与效益的二维归一化分类法,结合中位数分割与K-means聚类,将关键词科学划分为黄金词、重点词、潜力词、问题词和无效词五类。为实现效益最大化,建立以注册量为目标、受日预算与总预算约束的0-1整数规划模型,采用“贪心选词+拉格朗日对偶定价”的两阶段算法求解,显著降低单位注册成本,优化预算结构并提升展位质量。进一步引入CVaR鲁棒优化框架,对竞价、展现、点击、转化等环节的不确定性进行建模,生成更具风险抵御能力的投放策略,实证明优化后单位注册成本下降约两成,黄金词预算占比大幅提升,无效词被完全剔除,整体投放效能显著增强。; 适合人群:具备数据分析与建模基础,从事数字营销、运筹优化或相关领域研究的学生、研究人员及从业者。; 使用场景及目标:①学习如何系统性诊断广告投放效果并识别关键影响因素;②掌握基于数据驱动的关键词价值分类方法与多阶段优化求解技术;③理解并应用鲁棒优化思想处理营销决策中的不确定性问题。; 阅读建议:此资源不仅提供了完整的建模流程与算法实现,还包含详实的实证分析与策略对比,建议读者结合文中模型推导、算法步骤与结果解读进行深入学习,并尝试复现相关计算过程以加深理解。
内容概要:本文档是一份涵盖电力电子、新能源、优化算法、信号处理、无人机控制及数学建模等多个工程与科研领域的综合性技术资源集合。核心内容之一是基于三相PWM电压源换流器(VSC)构建的交流-直流-交流脉宽调制转换器的SimPowerSystems仿真模型,利用Simulink实现对整流、逆变及能量控制过程的建模与分析。此外,文档还整合了大量MATLAB/Simulink与Python代码实例,涉及微电网调度、负荷预测、路径规划、图像处理、状态估计等方向,并提供全国大学生数学建模竞赛题目的解决方案与仿真资源,突出理论建模与仿真实践深度融合的特点。; 适合人群:电气工程、自动化、控制科学与工程及相关专业的高校师生;从事电力系统、新能源、智能控制等领域研究的科研人员及工程师;参加数学建模竞赛的学生和技术爱好者。; 使用场景及目标:①深入理解三相PWM整流与逆变技术的工作原理,掌握Simulink建模仿真方法;②开展微电网优化、无人机路径规划、信号处理等相关课题的研究与算法验证;③备战全国大学生数学建模竞赛,获取题目解析、代码支持与论文参考;④作为课程设计、毕业设计或科研项目的教学辅助资料。; 阅读建议:此资源以具体工程项目和算法实现为导向,建议读者结合Simulink/MATLAB或Python环境动手实践,重点关注模型结构设计、参数设置与仿真结果分析,同时可参照提供的代码示例进行修改与扩展,全面提升理论理解与实际应用能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值