OpenHarmony HSP 动态分包完整实战:分包加载、传参、卸载避坑全流程
2026/7/22 23:05:18 网站建设 项目流程

前言

在大型鸿蒙项目、毕设项目中,如果所有页面全部打包进 entry 主模块,会出现安装包体积大、冷启动缓慢、闲置页面持续占用内存等问题。HSP(Harmony Shared Package)动态分包是官方提供的按需加载方案,重型编辑器、相册、视频页面可独立拆分为分包,仅用户点击时加载,退出页面立即卸载释放内存。 本文基于前文四层脚手架,完整演示 HSP 创建、依赖配置、页面跳转传参、分包卸载、常见报错解决方案,所有代码可直接复制运行。

一、HSP 与 HAR 核心区别

表格

类型HAR 静态包HSP 动态分包
加载时机编译期合并入主包,应用启动全部加载运行时按需加载,未访问不占用内存
页面支持不能存放 pages 路由页面支持独立 pages 页面,可单独跳转
依赖规则可被所有模块静态引入,不能依赖 HSP仅能依赖 HAR,不能依赖其他 HSP
复用范围全工程跨模块复用仅当前应用内部使用,无法跨项目共享
适用场景通用工具、业务实体、基础组件低频、体积大的独立业务页面

二、新建 HSP 模块与 module.json5 标准配置

1. 创建 hsp_note_editor 模块

DevEco Studio 右键项目 → New → Module → Harmony Shared Package,模块名hsp_note_editor

2. module.json5 完整配置

json

{ "module": { "name": "hsp_note_editor", "type": "hsp", "description": "笔记编辑器动态分包", "deviceTypes": ["phone"], "deliveryWithInstall": true, "pages": [ "src/main/ets/pages/EditorPage" ] }, "dependencies": [ { "name": "har_base", "version": "1.0.0", "scope": "shared" }, { "name": "har_note", "version": "1.0.0", "scope": "shared" } ] }

关键配置说明:

  1. deliveryWithInstall: true:打包时分包独立拆分,安装主 HAP 时同步安装分包;
  2. pages 数组注册分包内页面,否则路由跳转提示页面不存在;
  3. 仅依赖底层公共 HAR 与对应业务 HAR,禁止引入其他 HSP。

3. entry 模块依赖配置

entry 的 module.json5 dependencies 中添加该分包,否则编译找不到模块:

json

{ "name": "hsp_note_editor", "version": "1.0.0", "scope": "shared" }

三、HSP 跳转路由工具完整实现(承接上文 RouterUtil)

har_base/utils/router_util.ets补充 HSP 跳转方法,内置登录拦截、异常捕获:

ets

// HSP页面跳转 pushHsp(hspName: string, pagePath: string, params?: Object) { // 登录拦截,未登录禁止进入分包页面 if (!this.checkLogin()) return; try { router.pushNamedRoute({ bundleName: this.ctx?.bundleName, moduleName: hspName, pagePath: pagePath, params }) } catch (e) { LogUtil.error("RouterUtil", "HSP页面跳转失败", e); DialogUtil.alert({ content: "编辑器加载失败,请重试" }); } } // 卸载HSP分包,释放内存 async unloadHsp(hspName: string) { try { await router.unloadNamedRoute(hspName); LogUtil.info("RouterUtil", `分包${hspName}卸载完成`); } catch (e) { LogUtil.warn("RouterUtil", "分包卸载异常", e); } }

四、HSP 编辑器页面完整代码(hsp_note_editor/pages/EditorPage.ets)

ets

import ThemeUtil from '@ohos:har_base/utils/theme' import DialogUtil from '@ohos:har_base/utils/dialog_util' import RouterUtil from '@ohos:har_base/utils/router_util' import RdbUtil from '@ohos:har_base/utils/rdb_util' import LogUtil from '@ohos:har_base/utils/log_util' @Entry @Component struct EditorPage { @State title: string = "" @State content: string = "" // 接收列表页传递的笔记id,新增为0 @State noteId: number = 0 aboutToAppear() { // 获取路由传递参数 const params = router.getParams() as { id?: number } if (params.id && params.id > 0) { this.noteId = params.id this.loadEditNote() } } // 编辑模式:回填原有笔记数据 async loadEditNote() { const list = await RdbUtil.queryNoteList(0, 100); const target = list.find(item => item.id === this.noteId); if (target) { this.title = target.title this.content = target.content } } // 保存笔记 async saveNote() { if (!this.title.trim()) { DialogUtil.alert({ content: "标题不能为空" }) return } try { if (this.noteId > 0) { // 更新已有笔记 await RdbUtil.updateNote(this.noteId, this.title, this.content) } else { // 新增笔记 await RdbUtil.insertNote(this.title, this.content) } DialogUtil.alert({ content: "保存成功", onConfirm: async () => { // 返回列表页,卸载当前分包释放内存 RouterUtil.back() await RouterUtil.unloadHsp("hsp_note_editor") } }) } catch (err) { LogUtil.error("EditorPage", "保存笔记失败", err) DialogUtil.alert({ content: "保存失败,请重试" }) } } // 页面销毁强制卸载分包,防止内存残留 async aboutToDisappear() { DialogUtil.closeAllDialog() await RouterUtil.unloadHsp("hsp_note_editor") } build() { const color = ThemeUtil.getColor() const size = ThemeUtil.getSize() Column({ space: size.gapLg }) .width("100%") .height("100%") .padding(size.gapMd) .backgroundColor(color.pageBg) { Text(this.noteId > 0 ? "编辑笔记" : "新建笔记") .fontSize(size.fontTitle) .fontColor(color.textPrimary) TextInput({ text: this.title, placeholder: "请输入笔记标题" }) .width("100%") .height(size.btnNormal) .fontSize(size.fontMain) .backgroundColor(color.cardBg) .borderRadius(size.radiusSm) .onChange((val: string) => this.title = val) TextArea({ text: this.content, placeholder: "请输入笔记内容" }) .width("100%") .layoutWeight(1) .fontSize(size.fontAux) .backgroundColor(color.cardBg) .borderRadius(size.radiusSm) .onChange((val: string) => this.content = val) Button("保存笔记") .width("100%") .height(size.btnNormal) .backgroundColor(color.primary) .borderRadius(size.radiusSm) .onClick(() => this.saveNote()) } } }

五、entry 首页跳转 HSP 调用示例

ets

import RouterUtil from '@ohos:har_base/utils/router_util' import ThemeUtil from '@ohos:har_base/utils/theme' @Entry @Component struct IndexPage { build() { const color = ThemeUtil.getColor() const size = ThemeUtil.getSize() Column({ space: size.gapLg }) .width("100%") .height("100%") .padding(size.gapMd) .backgroundColor(color.pageBg) { Text("笔记管理首页") .fontSize(size.fontTitle) .fontColor(color.textPrimary) Button("新建笔记") .width("100%") .height(size.btnNormal) .backgroundColor(color.primary) .borderRadius(size.radiusSm) .onClick(() => { // 跳转HSP,传参id=0代表新建 RouterUtil.pushHsp("hsp_note_editor", "src/main/ets/pages/EditorPage", { id: 0 }) }) Button("查看笔记列表") .width("100%") .height(size.btnNormal) .backgroundColor(color.success) .borderRadius(size.radiusSm) .onClick(() => RouterUtil.push("pages/note/NoteListPage")) } } }

六、HSP 核心规范与内存优化要点

  1. 分包卸载强制规范页面aboutToDisappear生命周期必须调用unloadNamedRoute卸载分包,否则分包代码、图片资源常驻内存,多次进出内存持续上涨。
  2. 资源隔离规范HSP 内部图片、矢量图标添加分包专属前缀editor_,避免和 entry、HAR 资源重名打包覆盖。
  3. 禁止跨 HSP 引用hsp_a 不能导入 hsp_b 的任何 ets 代码,跨分包交互只能通过路由传参,不能静态 import。
  4. 数据存储规范分包不能独立封装数据库逻辑,所有 RDB 操作统一调用业务 HAR 提供的工具,分包仅做页面渲染。
  5. 全局状态规范分包可正常使用 GlobalStore 全局状态、ThemeUtil 主题工具,底层 HAR 全局能力完全共享。

七、HSP 高频报错与解决方案

报错 1:pushNamedRoute 提示页面不存在

原因 1:HSP 模块 module.json5 中 pages 数组未注册页面路径; 原因 2:跳转 pagePath 路径拼写错误,大小写不匹配; 解决:核对 pages 配置,复制完整页面文件路径填入路由参数。

报错 2:编译提示模块找不到

原因:entry 模块 dependencies 未添加 HSP 依赖; 解决:entry 的 module.json5 添加对应 HSP 依赖,同步清理项目缓存重新编译。

报错 3:多次打开分包内存持续升高

原因:页面退出未调用 unloadHsp 卸载分包、图片 PixelMap 未释放、全局监听未解绑; 解决:aboutToDisappear 统一执行卸载分包、关闭弹窗、释放图像资源。

报错 4:HSP 无法跳转其他 HSP 页面

原因:官方限制 HSP 之间不能互相路由跳转; 解决:返回 entry 主页面,由 entry 统一调度跳转不同分包。

报错 5:分包内深色模式切换无响应

原因:分包内部缓存主题色值,未实时调用 ThemeUtil.getColor (); 解决:build 方法内直接动态获取主题,不使用 @State 缓存颜色变量。

八、文末总结

HSP 动态分包是鸿蒙项目轻量化、性能优化的核心手段,将低频重型页面独立拆分,大幅缩减主 HAP 体积、降低冷启动耗时。结合前文四层架构,业务页面拆分至 HSP、基础能力下沉 HAR,实现代码复用与按需加载双重收益。 本文完整覆盖 HSP 创建、依赖配置、路由跳转、参数传递、分包卸载全流程,配套可直接运行的编辑器页面代码,解决分包开发 90% 常见报错,适合毕设、商用项目直接落地。 下一篇将讲解 OpenHarmony 图片压缩、相册权限完整工具 ImagePickerUtil 实战。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询