一、鸿蒙应用分包基础概念

鸿蒙应用采用模块化分包架构,核心分为 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"
    }
}

注释讲解

  1. name:当前模块名称,依赖其他模块时通过该字段引用;
  2. type:模块类型,hap 代表可独立安装运行的应用模块;
  3. version:模块版本,code 为数字版本号用于升级校验,name 为展示用版本字符串;
  4. deviceTypes:声明适配设备类型,当前支持手机、平板、二合一设备;
  5. 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"
    }
}

注释讲解

  1. name、version:当前 HAP 模块包名与版本;
  2. dependencies:依赖列表,配置项目需要引入的 HAR/HSP 模块;
  3. 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 使用场景限制

  1. 不支持定义 Ability、页面路由,无法独立安装;
  2. 多模块同时依赖同一 HAR 会产生代码冗余;
  3. 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 开发约束

  1. 仅可被 HAP 引用加载,不能作为应用入口模块;
  2. HSP 可依赖 HAR 静态库,不支持依赖其他 HSP;
  3. 适合大型复用业务、图片资源库、复杂通用逻辑封装。

五、HAP / HAR / HSP 选型对比与工程分层建议

5.1 三类分包核心差异

表格

包类型 加载时机 能否独立安装 代码复用特点 适用场景
HAP 应用安装即加载 支持 独立运行,模块隔离 应用入口、页面、Ability、独立业务
HAR 编译期合并打包 不支持 静态拷贝,多依赖存在冗余 轻量工具、基础组件、常量封装
HSP 运行时动态按需加载 不支持 全局单份代码,多模块共享 大型通用业务、资源库、减少包体积

5.2 工程分层开发建议

  1. 底层基础工具、通用常量、基础 UI 组件封装为 HAR;
  2. 多业务模块共用的复杂业务逻辑封装为 HSP,避免代码冗余;
  3. 页面、Ability、业务入口全部放置在 Entry、Feature 类型 HAP;
  4. 规避循环依赖:禁止 HSP 互相依赖,HAP 可同时依赖 HAR 与 HSP。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐