OpenHarmony HSP 动态共享库 按需分包加载(API Version23)
摘要
HAR 是静态打包,全部代码安装时一次性装入主包,APP 体积大、冷启动慢;HSP(Harmony Shared Package)动态共享库支持运行时按需加载,将非核心业务拆分独立动态包,首页仅加载基础模块,其他功能进入对应页面时再动态拉取 / 加载,减小安装包体积、缩短启动耗时。API23 重构 HSP 动态加载上下文、页面路由跳转、资源隔离、内存释放逻辑,修复低版本 HSP 页面跳转空白、动态组件渲染失败、包重复加载内存泄漏、资源跨包访问崩溃等问题。本文完整讲解 HSP 创建、依赖配置、动态加载页面 / 工具 / 组件、分包路由、资源隔离、卸载回收,配套笔记业务 HSP 实战工程,对比 HAR 与 HSP 适用场景,给出分包优化规范,适配课程设计大型多模块项目、商用轻量化 APP 开发。
关键词
OpenHarmony;ArkTS;API23;HSP;动态共享包;按需加载;分包;动态路由;包体积优化
一、引言
1.1 HSP 开发背景
静态 HAR 全部代码编译打包进 entry 主模块,存在明显短板:
- 功能越多安装包越大,低端设备安装缓慢;
- 首次启动需要加载全部代码,冷启动卡顿;
- 低频功能(笔记、相册、设置)长期占用内存,后台耗电;
- 多业务耦合,删除功能需要重新全量编译。
HSP 动态共享库解决以上痛点:
- 代码、资源独立分包,运行时按需加载,不用不占用内存;
- 主包仅保留首页、登录、基础工具,大幅缩减安装包体积;
- 低频业务拆分为独立 HSP,进入页面时再加载包;
- 支持动态卸载,退出业务页面释放整个分包内存。
OpenHarmony API23 HSP 核心升级点:
- 新增 loadPackage/waitPackageLoad 统一加载 API,简化异步等待逻辑;
- 隔离 HSP 与主包资源域,避免图片、常量重名冲突;
- 修复动态加载页面返回栈错乱、路由丢失;
- 完善包卸载资源回收:组件、数据库、定时器自动释放;
- 支持 HSP 内部再次依赖基础 HAR,复用公共工具;
- 严格限制跨包直接导入,统一使用动态导入接口,杜绝编译爆红。
1.2 HSP 与 HAR 核心区分
表格
| 类型 | 加载时机 | 包体积 | 跨包导入方式 | 适用场景 |
|---|---|---|---|---|
| HAR 静态库 | 编译打包,安装即加载 | 合并入主包,包大 | import 静态导入 | 全局基础工具、高频公共组件 |
| HSP 动态库 | 运行时按需动态加载 | 独立分包,主包极小 | 动态 loadPackage + 反射调用 | 低频独立业务:笔记、相机相册、设置 |
二、API23 HSP 核心配置与基础 API
2.1 HSP 模块 module.json5 基础配置
json
{
"module": {
"name": "hsp_note",
"type": "hsp",
"description": "笔记动态分包",
"deviceTypes": ["phone"],
"deliveryWithInstall": true,
"installationFree": false,
"pages": [
"src/main/ets/pages/NoteList"
],
"dependencies": [
{
"name": "har_base",
"version": "1.0.0",
"scope": "shared"
}
]
}
}
关键点:
- type 固定为
hsp; - HSP 内部可注册 pages 页面,独立路由;
- 仅能依赖静态 HAR,HSP 之间禁止互相依赖;
- deliveryWithInstall=true,打包时自动拆分独立分包。
2.2 entry 主模块依赖 HSP(仅声明,不静态合并)
json
"dependencies": [
{
"name": "hsp_note",
"version": "1.0.0",
"scope": "shared"
}
]
2.3 动态加载核心 API
ets
import hspManager from '@ohos.hspManager'
// 1. 异步加载HSP包
await hspManager.loadPackage("hsp_note")
// 2. 等待包加载完成,获取包上下文
const hspContext = await hspManager.waitPackageLoad("hsp_note")
// 3. 卸载分包,释放全部资源
hspManager.unloadPackage("hsp_note")
// 4. 跳转HSP内部页面(包名://页面路径)
router.pushUrl({url: "hsp_note/pages/NoteList"})
2.4 API23 强制约束
- 禁止直接 import 导入 HSP 内部 ets 代码,必须动态加载后反射调用;
- HSP 页面路由格式固定:
hsp包名/页面完整pages路径; - HSP 不能定义 UIAbility,生命周期统一由 entry 主 Ability 管理;
- 跨 HSP 资源不能直接 $r 引用,需通过全局 HAR 共享资源;
- 页面退出必须 unloadPackage 释放分包,防止内存持续上涨;
- 同一分包不可重复并发 loadPackage,增加加载状态锁防重复请求。
三、最简基础示例:动态加载并跳转 HSP 页面
entry 首页跳转笔记分包
ets
import hspManager from '@ohos.hspManager'
import router from '@ohos.router'
import { showToast } from '@ohos:har_base/utils/toast_util'
@Entry
@Component
struct Index {
@State loading: boolean = false
async jumpNoteHsp() {
if (this.loading) return
this.loading = true
try {
// 加载笔记动态分包
await hspManager.loadPackage("hsp_note")
showToast("笔记模块加载完成")
// 跳转HSP内部页面
router.pushUrl({ url: "hsp_note/src/main/ets/pages/NoteList" })
} catch (err) {
showToast("动态模块加载失败")
console.error("hsp加载异常", err)
} finally {
this.loading = false
}
}
build() {
Column() {
Text("主应用首页(仅基础包)").fontSize(24).margin({ top: 80 })
Button(this.loading ? "加载中..." : "打开笔记模块(动态HSP)")
.width(300)
.height(48)
.margin({ top: 30 })
.onClick(() => this.jumpNoteHsp())
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
}
HSP 笔记页面 hsp_note/src/main/ets/pages/NoteList.ets
ets
import NoteDbUtil from '@ohos:har_base/db/note_db'
import { NoteItemCard } from '@ohos:har_base/components/NoteItemCard'
import { NoteItem } from '@ohos:har_base/model/NoteModel'
import router from '@ohos.router'
import hspManager from '@ohos.hspManager'
@Entry
@Component
struct NoteList {
@State list: NoteItem[] = []
async aboutToAppear() {
const ctx = getContext(this)
NoteDbUtil.setContext(ctx)
await NoteDbUtil.init()
this.list = await NoteDbUtil.queryList(0, 10)
}
// 返回首页并卸载HSP分包释放内存
backHome() {
router.back()
// 卸载动态包
hspManager.unloadPackage("hsp_note")
}
build() {
Column({ space: 12 }) {
Row() {
Button("返回首页并释放分包").onClick(() => this.backHome())
Text("笔记动态分包页面(HSP)").layoutWeight(1).fontSize(20)
}
List({ space: 10 }).layoutWeight(1) {
ForEach(this.list, (item: NoteItem) => {
ListItem() {
NoteItemCard({ data: item })
}
})
}
}
.width("100%")
.height("100%")
.padding(12)
.backgroundColor("#f5f5f5")
}
async aboutToDisappear() {
await NoteDbUtil.closeDB()
}
}
四、实战封装:HSP 动态加载工具类 utils/hsp_load_util.ets
ets
import hspManager from '@ohos.hspManager'
import router from '@ohos.router'
import promptAction from '@ohos.promptAction'
class HspLoadUtil {
private static instance: HspLoadUtil
// 记录正在加载的分包,防重复并发加载
private loadingMap: Map<string, boolean> = new Map()
static getInstance(): HspLoadUtil {
if (!HspLoadUtil.instance) HspLoadUtil.instance = new HspLoadUtil()
return HspLoadUtil.instance
}
// 加载分包并跳转内部页面
async loadAndJump(hspName: string, pagePath: string): Promise<boolean> {
if (this.loadingMap.get(hspName)) {
promptAction.showToast({ message: "模块正在加载,请稍等" })
return false
}
this.loadingMap.set(hspName, true)
try {
// 加载分包
await hspManager.loadPackage(hspName)
// 等待包就绪
await hspManager.waitPackageLoad(hspName)
// 跳转页面
router.pushUrl({ url: `${hspName}/${pagePath}` })
return true
} catch (e) {
promptAction.showToast({ message: "功能模块加载失败" })
console.error(`HSP[${hspName}]加载失败`, e)
return false
} finally {
this.loadingMap.set(hspName, false)
}
}
// 卸载分包,释放资源
unload(hspName: string) {
hspManager.unloadPackage(hspName)
this.loadingMap.delete(hspName)
}
}
export default HspLoadUtil.getInstance()
工具调用示例
ets
import HspLoadUtil from '../utils/hsp_load_util'
// 点击按钮加载笔记分包并跳转页面
Button("打开笔记模块")
.onClick(async ()=>{
await HspLoadUtil.loadAndJump("hsp_note", "src/main/ets/pages/NoteList")
})
五、HSP 分包工程分层架构规范
标准三层架构
- entry(主包)
- 首页、登录、全局状态、EntryAbility、HSP 加载工具
- 仅依赖基础 har_base,不包含任何低频业务代码
- har_base(静态公共库)
- 全局工具、数据模型、通用 UI 组件、常量
- entry 与所有 HSP 统一依赖,共享无重复代码
- hsp_xxx(各业务动态分包)
- hsp_note 笔记模块
- hsp_camera 相机相册模块
- hsp_setting 设置模块 每个 HSP 仅依赖 har_base,互相不依赖,独立按需加载、卸载
分包拆分标准
- 必须放入主 entry:登录、首页、全局基础工具、启动逻辑;
- 适合拆 HSP:低频独立完整业务,页面不与首页强耦合;
- 禁止拆 HSP:全局高频组件、通用工具(统一放入 HAR)。
六、性能与内存优化规范
- 加载时机优化:不在 aboutToAppear 自动预加载 HSP,用户点击按钮再加载,减少冷启动耗时;
- 内存释放强制规范:退出 HSP 业务页面必须调用 unloadPackage,释放数据库、定时器、组件缓存;
- 防重复加载:工具类增加 loadingMap 状态锁,避免快速点击重复触发 loadPackage;
- 资源复用规范:图片、字体、通用组件全部放入 har_base,HSP 不重复存放资源,减小分包体积;
- 避免嵌套加载:禁止在一个 HSP 内部加载另一个 HSP,统一由 entry 主包管理分包加载逻辑;
- 分包体积控制:单个 HSP 控制在 10MB 以内,超大业务继续拆分为多个小 HSP。
七、API23 升级常见问题解决方案
问题 1:跳转 HSP 页面提示页面不存在 解决:路由路径完整填写 hsp包名/完整页面文件路径,核对 module.json5 中 pages 注册路径。
问题 2:多次点击按钮重复加载,应用卡顿 解决:使用 Map 标记加载状态,加载中拦截重复点击。
问题 3:退出页面不卸载 HSP,内存持续上涨 解决:页面返回时调用 hspManager.unloadPackage 释放分包资源。
问题 4:HSP 中使用 RDB/Preferences 上下文失效 解决:HSP 页面通过 getContext (this) 获取上下文,传入 HAR 工具类,不要使用 entry 全局上下文。
问题 5:编译提示 HSP 之间存在依赖循环 解决:HSP 仅允许依赖静态 har_base,所有 HSP 互相不引用。
问题 6:打包后分包未拆分,全部合并进 entry 解决:HSP 模块 deliveryWithInstall 配置为 true,重新构建 App 包。
八、总结
HSP 动态共享包是 OpenHarmony 官方分包体积优化方案,API23 完善动态加载、等待就绪、卸载回收、路由跳转整套能力,完美解决静态 HAR 打包主包体积大、冷启动慢、低频功能常驻占用内存等痛点。 工程采用「entry 主包 + HAR 公共底层 + 多 HSP 业务分包」三层标准架构,高频基础能力静态复用,低频独立业务按需动态加载、用完卸载释放内存,兼顾启动速度、安装包大小、内存占用三大性能指标。 代码完全兼容 API23 / HarmonyOS NEXT,适合大型综合课程设计、商用轻量化鸿蒙 APP 分包改造。
更多推荐



所有评论(0)