深入解析:鸿蒙 Stege模型 多模块应用

模块

一个鸿蒙应用可能包含一个或者多个功能模块,在 DevEcoStudio 工程中可以创建对应的一个或多个 Module。Module 又分为 “Ability” 和 “Library”两种类型,“Ability”类型的 Module 对应于编译后的 HAP(Harmony Ability Package);“Library” 类型的 Module 对应于 HAR (Harmony Archive),或者 HSP (Harmony Shared Package)

三类模块

HAP (Harmony Ability Package)HAR (Harmony Archive)HSP (Harmony Shared Package)
功能说明及适用场合分为 entryfeature;应用的功能模块,可以独立安装和运行静态共享包,编译态复用。- 多包(HAP/HSP)引用相同的 HAR 时,会造成多包间代码和资源的重复拷贝,从而导致应用包膨大动态共享包,运行时复用。- 当多包(HAP/HSP)同时引用同一个共享包时,可以避免 HAR 造成的多包间代码和资源的重复拷贝,从而减少小应用包大小
支持在配置文件中声明 UIAbility 组件与 ExtensionAbility 组件
支持在配置文件中声明 pages 页面
支持包含资源文件与.so 文件
支持依赖其他 HAR 文件
支持依赖其他 HSP 文件
支持在设备上独立安装运行

HAP

HAP(Harmony Ability Package)是应用安装和运行的基本单元。HAP 包是由代码、资源、第三方库、配置文件等打包生成的模块包;主要分为两种类型:entry 和 feature:

  1. entry:应用的主模块,作为应用的入口,提供了应用的基础功能;
  2. feature:应用的动态特性模块,作为应用能力的扩展,可以根据用户的需求和设备类型进行选择性安装;

应用程序包可以只包含一个基础的 entry 包,也可以包含一个基础的 entry 包和多个功能性的 feature 包

//module.json5
{
"module": {
"name": "video",
"type": "entry",
"mainElement": "VideoAbility"
}
}
//module.json5
{
"module": {
"name": "mall",
"type": "feature",
"mainElement": "MallAbility"
}
}

注意:不支持导出 HAP 中的接口和 ArkUI 组件,供其他 HAR/HSP 模块使用!!

HSP

HSP(Harmony Shared Package)是动态共享包,可以包含代码、C++库、资源和配置文件,通过 HSP 可以实现代码和资源的共享。HSP 不支持独立发布,而是跟随其宿主应用的 APP 包一起发布,与宿主应用同进程,具有相同的包名和生命周期。主要使用场景:

  1. 多 HAP 或者 HSP 共用的代码、资源可以使用 HSP,提高代码的可重用性和可维护性;
  2. 按需加载,HSP 包在运行时再按需加载;
  3. 元服务分包及预加载;
//module.json5
{
"module": {
"name": "mylib01",
"type": "shared",
"deviceTypes": ["phone", "tablet"],
"deliveryWithInstall": true,
"pages": "$profile:main_pages"
}
}

HAR

HAR(Harmony Archive)是静态共享包,可以包含代码、C++库、资源和配置文件。通过 HAR 可以实现多个模块或多个工程共享 ArkUI 组件、资源等相关代码。使用场景:

  1. 导出公共 ArkUI 组件或 ts 类/方法供当前应用的其它 HAP 和 HSP 使用;
  2. 作为二方库,发布到 OHPM 私仓,供公司内部其他应用使用;
  3. 作为三方库,发布到 OHPM 中心仓,供其他应用使用;
//module.json5
{
"module": {
"name": "mylib02",
"type": "har",
"deviceTypes": ["default", "tablet"]
}
}

注意:HAR 模块默认不提供 pages,也没有 UIAbility

HAP 模块跳转

模块内跳转

在同一个 HAP 中的多个 Page 间跳转:多个页面共用同一个窗口

//模块内多个页面间跳转
router.pushUrl({
url: "pages/Details",
});

在同一个 HAP 中的多个 UIAbility 间跳转:每个页面都有独立的窗口

//模块内多个UIAbility间跳转
const want: Want = {
deviceId: "", //可选,传空表示本设备
bundleName: "cn.baidu.myapp", //必需,应用唯一标识
moduleName: "entry", //可选,模块名称
abilityName: "ChatAbility", //必需,UIAbility名称
};
let ctx = getContext(this) as common UIAbilityContext
ctx.startAbility(want)
跨 HAP 模块跳转

每个 HAP 上架到应用商店都是可以根据客户端设备情况独立安装的,如果希望跳转到其它模块,必须在当前模块的编译配置中声明“多 Hap 同时部署(Deploy Multi Hap)”

//跨多个HAP模块跳转
let want: Want = {
deviceId: "", //传空表示本设备
bundleName: "cn.baidu.myapp", //应用唯一标识
moduleName: "mall", // *******模块名称*********
abilityName: "MallAbility", //UIAbility名称
};
let ctx = getContext(this) as common.UIAbilityContext;
ctx.startAbility(want);

跨模块的多个页面也都有各自的运行时窗口

使用 HSP

导出公共页面

HSP 模块中可以创建公共页面,并导出,从而供多个 HAP 来使用

//mylib01/src/main/ets/pages/Login.ets
@Entry
@Component
export struct Login {
build() {
Row() {
Column() {
Text('Library Page')
}
.width('100%')
}
.height('100%')
}
}
//entry/src/main/ets/pages/Index.ets
router.pushUrl({
url: "@bundle:cn.baidu.myapp/mylib01/ets/pages/Login",
});

URL 格式为:
@bundle:包名/模块名/路径/页面所在的文件名(不加.ets 后缀)
且“路径”中没有 src/main (部署态不存在这两个目录)!

注意
必须在 HAP 模块的编译配置中声明“多 Hap 同时部署(Deploy Multi Hap)”,其中勾选 HSP 模块

说明:HSP 模块中是没有 UIAbility 的!只能运行在 HAP 提供的窗口中

导出公共组件

HSP 模块中可以创建公共组件,并导出,从而供多个 HAP 来使用

//mylib01/src/main/ets/components/TitleBar.ets
@Preview
@Component
export struct TitleBar {
build() {
Row() {
Text('Title Bar')
}
.width('100%')
.height(45)
}
}
//mylib01/Index.ets
export { TitleBar
} from "./src/main/ets/components/TitleBar";
//entry/oh-package.json5
{
"dependencies": {
"mylib01": "file:../mylib01"
}
}
//entry/src/main/ets/pages/Index.ets
import { TitleBar
} from 'mylib01'
@Entry
@Component
struct Index {
build() {
Column() {
TitleBar()
}
}
}
导出公共对象和方法

HSP 模块中可以创建公共对象和方法,并导出,从而供多个 HAP 来使用

//mylib01/src/main/ets/util/Calc.ets
export function add(a: number, b: number) {
return a + b;
}
export function sub(a: number, b: number) {
return a - b;
}
//mylib01/Index.ets
export { add, sub
} from "./src/main/ets/utils/Calc";
//entry/oh-package.json5
{
"dependencies": {
"mylib01": "file:../mylib01"
}
}
//entry/src/main/ets/pages/Index.ets
import { add
} from 'mylib01'
build() {
Column() {
Button('相加').onClick(_ =>
{
add(10, 20)
})
}
}

使用 HAR

导出 pages 页面

HAR 不支持在配置文件中声明 pages 页面,但是可以包含 pages 页面,并通过命名路由的方式进行跳转

//mylib02/src/main/ets/pages/MyPage.ets
@Entry({ routeName: 'myPage'
})
@Component
export struct MyPage {
build() {
Row() {
Text('My Page')
}
.width('100%')
.height('100%')
}
}
//mylib02/Index.ets
//命名路由页面无需导出
//entry/oh-package.json5
{
"dependencies": {
"mylib02": "file:../mylib02"
}
}
//entry/src/main/ets/pages/Index.ets
import('mylib02/src/main/ets/pages/MyPage')
@Entry
@Component
struct Index {
build() {
Button('跳转到HAR中的页面').onClick(_ =>
{
router.pushNamedRoute({
name: 'myPage', //页面名称
params: {
} //自定义的路由参数
})
})
}
}
导出公共组件

HAR 模块中可以创建公共组件,并导出,从而供多个 HAP 来使用

//mylib02/src/main/ets/components/TitleBar.ets
@Preview
@Component
export struct TitleBar {
build() {
Row() {
Text('Title Bar')
}
.width('100%')
.height(45)
}
}
//mylib02/Index.ets
export { TitleBar
} from "./src/main/ets/components/TitleBar";
//entry/oh-package.json5
{
"dependencies": {
"mylib02": "file:../mylib02"
}
}
//entry/src/main/ets/pages/Index.ets
import { TitleBar
} from 'mylib02'
@Entry
@Component
struct Index {
build() {
Column() {
TitleBar()
}
}
}
导出公共对象和方法

HAR 模块中可以创建公共对象和方法,并导出,从而供多个 HAP 来使用

//mylib02/src/main/ets/util/Calc.ets
export function add(a: number, b: number) {
return a + b;
}
export function sub(a: number, b: number) {
return a - b;
}
//mylib02/Index.ets
export { add, sub
} from "./src/main/ets/utils/Calc";
//entry/oh-package.json5
{
"dependencies": {
"mylib02": "file:../mylib02"
}
}
//entry/src/main/ets/pages/Index.ets
import { add
} from 'mylib02'
build() {
Column() {
Button('相加').onClick(_ =>
{
add(10, 20)
})
}
}
posted on 2025-07-17 13:33  ljbguanli  阅读(28)  评论(0)    收藏  举报