【无标题】
·
一、鸿蒙应用分包基础概念
鸿蒙应用采用模块化分包架构,核心分为 HAP、HAR、HSP 三类程序包,三者各司其职,分别对应应用运行载体、静态代码复用、动态共享模块,是大型鸿蒙项目工程化开发的核心基础。
- HAP(Harmony Ability Package):应用可独立安装运行的主体模块,承载页面、Ability、业务逻辑;
- HAR(Harmony Archive):静态代码资源归档库,编译期合并至宿主模块,适合轻量通用能力封装;
- HSP(Harmony Shared Package):动态共享包,运行时按需加载,多模块共享同一份代码资源,缩减安装包体积。
二、HAP 应用主模块开发实践
HAP 是应用分发运行的最小单元,项目中分为 Entry HAP(应用唯一入口)与 Feature HAP(业务分模块)。
2.1 module.json5 模块配置文件
{
"name": "entry",
"type": "hap",
"description": "应用主入口模块",
"version": {
"code": 10001,
"name": "1.0.1"
},
"deviceTypes": [
"phone",
"tablet",
"2in1"
],
"entryAbility": {
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets"
}
}
注释讲解
- name:当前模块名称,依赖其他模块时通过该字段引用;
- type:模块类型,hap 代表可独立安装运行的应用模块;
- version:模块版本,code 为数字版本号用于升级校验,name 为展示用版本字符串;
- deviceTypes:声明适配设备类型,当前支持手机、平板、二合一设备;
- entryAbility:仅 Entry HAP 配置,标记应用启动入口 Ability,指定类名与文件路径。
2.2 入口 Ability 业务逻辑代码
// 导入UIAbility基础父类,所有页面入口Ability继承该类
import UIAbility from '@ohos.app.ability.UIAbility';
// 系统日志打印工具,用于控制台输出业务日志
import hilog from '@ohos.hilog';
// 日志域常量,统一大写命名,区分不同业务模块日志
const LOG_DOMAIN = 0x0005;
// 日志标签,过滤日志时快速定位当前模块输出
const LOG_TAG = "APP_MAIN";
// 最大等待时长常量,全局统一配置超时阈值
const MAX_WAIT_TIME = 3000;
// 导出应用入口Ability类,类文件承载应用生命周期回调
export default class EntryAbility extends UIAbility {
// 应用创建生命周期回调,应用启动时执行
onCreate(want, launchParam) {
// 从启动参数中获取启动模式,无参数则默认赋值0
let launchMode = want.parameters?.launchMode ?? 0;
// 常量写在左侧对比,规避赋值误写bug,0代表冷启动
if (0 == launchMode) {
hilog.info(LOG_DOMAIN, LOG_TAG, "应用冷启动流程");
}
// 1代表热启动,应用后台唤醒场景
else if (1 == launchMode) {
hilog.info(LOG_DOMAIN, LOG_TAG, "应用热启动流程");
}
// 调试开关布尔变量
let openDebug = true;
// 显式使用==判断布尔值,不简写if(openDebug)
if (true == openDebug) {
// 调用自定义日志初始化方法
this.Init_Log_Config();
}
}
// 日志延时配置初始化函数,函数名采用下划线分隔命名
Init_Log_Config() {
// 延时累加变量,初始值0
let delayTime = 0;
// 循环生成阶梯延时,i自增步长为1
for (let i = 0; i < 10; i += 1) {
// 算术运算符前后添加空格,每次叠加100ms延时
delayTime += i * 100;
// 判断延时是否达到预设最大阈值
if (MAX_WAIT_TIME <= delayTime) {
hilog.info(LOG_DOMAIN, LOG_TAG, "日志延时配置完成");
// 满足条件跳出循环,终止后续累加
break;
}
}
}
// 窗口实例创建回调,加载应用首页页面
onWindowStageCreate(windowStage) {
// 首页路由地址字符串
let homePage = "pages/main/index";
// 判断路由地址非空,避免加载空路径报错
if ("" != homePage) {
// 加载页面,回调接收错误码与返回数据
windowStage.loadContent(homePage, (code, data) => {
// 错误码不等于0代表页面加载失败
if (0 != code) {
hilog.error(LOG_DOMAIN, LOG_TAG, "首页加载失败,错误码:%d", code);
}
});
}
}
}
2.3 HAP 依赖配置 oh-package.json5
{
"name": "entry",
"version": "1.0.1",
"dependencies": {
"common_utils": "file:../common_utils",
"business_share": "file:../business_share"
}
}
注释讲解
- name、version:当前 HAP 模块包名与版本;
- dependencies:依赖列表,配置项目需要引入的 HAR/HSP 模块;
- file:xxx:本地文件路径依赖,指向同工程下其他模块目录。
三、HAR 静态资源库开发与引用
HAR 属于静态打包库,编译阶段会将全部代码、资源拷贝至依赖方,无独立运行能力,适合封装工具函数、基础 UI 组件、通用常量。
3.1 HAR 模块 module.json5
{
"name": "common_utils",
"type": "har",
"description": "全局通用工具静态库",
"version": {
"code": 2,
"name": "1.0.0"
}
}
注释讲解 type 设置为 har,标记当前模块为静态归档库,无法单独安装,仅作为依赖被其他模块编译合并。
3.2 HAR 工具类示例代码
// 文本输入最大长度限制常量
const MAX_INPUT_LENGTH = 128;
// 空字符串常量统一提取,避免硬编码""
const EMPTY_STR = "";
/**
* 校验输入文本长度合法性
* @param input 待校验字符串
* @returns 合法返回true,超出长度/非法值返回false
*/
export function Check_Text_Length(input: string): boolean {
// 获取输入字符串实际长度
let length = input.length;
// 长度超过上限 或 长度为负数,直接判定非法
if (MAX_INPUT_LENGTH < length || 0 > length) {
return false;
}
// 校验标记变量
let validFlag = true;
// 标记为false 或 输入为空字符串,判定非法
if (false == validFlag || EMPTY_STR == input) {
return false;
}
return true;
}
/**
* 计算两个数字换算后的总值
* @param numA 数字参数A
* @param numB 数字参数B
* @returns 换算后最终数值
*/
export function Calc_Total_Value(numA: number, numB: number): number {
// 基础计算公式,运算符前后空格分隔
let total = numA * 3 + numB - 2;
// 判断结果是否为奇数,取模运算判断奇偶
if (0 != total % 2) {
// 奇数则自增1转为偶数
total += 1;
}
return total;
}
3.3 HAR 使用场景限制
- 不支持定义 Ability、页面路由,无法独立安装;
- 多模块同时依赖同一 HAR 会产生代码冗余;
- HAR 模块内部不可引入 HSP 动态包。
四、HSP 动态共享包开发与运行加载
HSP 为运行时动态共享模块,多个 HAP 可共用一份代码资源,大幅降低应用整体包体积,支持按需延迟加载,适合大型复用业务模块。
4.1 HSP 模块基础配置
{
"name": "business_share",
"type": "hsp",
"description": "商品业务动态共享模块",
"version": {
"code": 1,
"name": "1.0.0"
},
"deviceTypes": [
"phone"
]
}
注释讲解 type 为 hsp,动态共享模块,编译不会拷贝代码,运行时由 HAP 动态导入复用。
4.2 HSP 对外导出业务类
// 导入日志工具,用于共享模块内部打印业务日志
import hilog from '@ohos.hilog';
// HSP模块独立日志域,和主模块日志隔离区分
const HSP_LOG_DOMAIN = 0x0006;
// HSP日志标签,快速筛选共享模块日志
const HSP_LOG_TAG = "HSP_GOODS";
// 商品最大数量上限常量
const MAX_GOODS_COUNT = 999;
/**
* 商品操作管理类,对外提供商品增减、数量查询能力
*/
export class Goods_Operate {
// 私有成员:当前商品库存数量
private currentCount = 0;
/**
* 增加商品数量
* @param addNum 新增商品数量
*/
Add_Goods_Count(addNum: number): void {
// 新增数量大于0 且 新增后不超过最大上限,才允许累加
if (0 < addNum && MAX_GOODS_COUNT >= this.currentCount + addNum) {
this.currentCount += addNum;
}
else {
// 不满足条件打印警告日志
hilog.warn(HSP_LOG_DOMAIN, HSP_LOG_TAG, "商品数量超出上限");
}
}
/**
* 获取当前库存商品总数
* @returns 当前商品数量
*/
Get_Current_Count(): number {
return this.currentCount;
}
}
/**
* 获取当前共享模块版本号
* @returns HSP版本字符串
*/
export function Get_Hsp_Version(): string {
// 版本常量统一大写定义
const HSP_VERSION_CODE = "1.0.0";
return HSP_VERSION_CODE;
}
4.3 HAP 动态加载 HSP 完整示例
// 导入日志工具,打印HSP加载过程日志
import hilog from '@ohos.hilog';
// 需要加载的共享模块名称,和HSP模块name保持一致
const HSP_MODULE_NAME = "business_share";
// HSP加载流程专属日志域
const LOAD_LOG_DOMAIN = 0x0007;
// HSP加载日志标签
const LOAD_LOG_TAG = "HSP_LOAD";
/**
* 异步加载商品业务HSP模块,校验模块导出接口可用性
*/
async function Load_Goods_Hsp() {
// HSP模块实例接收变量,初始空值
let hspInstance = null;
try {
// 动态导入指定名称的HSP模块,异步加载
hspInstance = await import(HSP_MODULE_NAME);
// 判断模块实例加载成功
if (null != hspInstance) {
// 实例化HSP导出的商品管理类
let goodsMgr = new hspInstance.Goods_Operate();
// 调用商品新增方法,传入20件商品
goodsMgr.Add_Goods_Count(20);
// 获取新增后商品数量
let realCount = goodsMgr.Get_Current_Count();
// 校验新增数量是否符合预期
if (20 == realCount) {
hilog.info(LOAD_LOG_DOMAIN, LOAD_LOG_TAG, "HSP商品模块加载校验通过");
}
// 获取HSP版本号
let hspVer = hspInstance.Get_Hsp_Version();
// 判断版本字符串非空,打印版本信息
if ("" != hspVer) {
hilog.info(LOAD_LOG_DOMAIN, LOAD_LOG_TAG, "当前共享模块版本:%s", hspVer);
}
}
}
catch (errorInfo) {
// 捕获加载异常,读取异常错误码
let errCode = errorInfo.code;
// -401代表模块不存在,给出明确提示
if (-401 == errCode) {
hilog.error(LOAD_LOG_DOMAIN, LOAD_LOG_TAG, "未找到对应HSP模块,请核对模块名称");
}
else {
// 其他未知异常打印原始错误信息
hilog.error(LOAD_LOG_DOMAIN, LOAD_LOG_TAG, "动态加载异常:%s", errorInfo.message);
}
}
}
// 页面入口装饰器,标记当前为ArkUI页面
@Entry
// 页面组件装饰器,声明自定义页面
@Component
struct GoodsPage {
// 状态变量,UI自动响应变量更新
@State statusText: string = "未加载业务共享模块";
build() {
// 根布局:纵向排列组件
Column() {
// 文本组件展示加载状态
Text(this.statusText)
.fontSize(24)
.margin({ bottom: 30 });
// 按钮触发HSP加载逻辑
Button("加载商品共享模块")
.fontSize(20)
.onClick(() => {
// 点击执行异步加载,加载完成更新页面状态文字
Load_Goods_Hsp().then(() => {
this.statusText = "HSP模块加载完成";
});
})
}
// 布局宽高铺满全屏,内边距30
.width("100%")
.height("100%")
.padding(30);
}
}
4.4 HSP 开发约束
- 仅可被 HAP 引用加载,不能作为应用入口模块;
- HSP 可依赖 HAR 静态库,不支持依赖其他 HSP;
- 适合大型复用业务、图片资源库、复杂通用逻辑封装。
五、HAP / HAR / HSP 选型对比与工程分层建议
5.1 三类分包核心差异
表格
| 包类型 | 加载时机 | 能否独立安装 | 代码复用特点 | 适用场景 |
|---|---|---|---|---|
| HAP | 应用安装即加载 | 支持 | 独立运行,模块隔离 | 应用入口、页面、Ability、独立业务 |
| HAR | 编译期合并打包 | 不支持 | 静态拷贝,多依赖存在冗余 | 轻量工具、基础组件、常量封装 |
| HSP | 运行时动态按需加载 | 不支持 | 全局单份代码,多模块共享 | 大型通用业务、资源库、减少包体积 |
5.2 工程分层开发建议
- 底层基础工具、通用常量、基础 UI 组件封装为 HAR;
- 多业务模块共用的复杂业务逻辑封装为 HSP,避免代码冗余;
- 页面、Ability、业务入口全部放置在 Entry、Feature 类型 HAP;
- 规避循环依赖:禁止 HSP 互相依赖,HAP 可同时依赖 HAR 与 HSP。
更多推荐


所有评论(0)