第2篇:鸿蒙 HAR 共享模块设计——多组件复用实践
·
第2篇:鸿蒙 HAR 共享模块设计——多组件复用实践
一、什么是 HAR(Harmony Archive)
HAR(Harmony Archive)是鸿蒙系统中的静态共享包,类似于 Android 的 AAR 或 iOS 的 Framework。一个 HAR 可以包含代码、资源、配置文件,供其他模块引用。在 DriverLicenseExam 项目中,HAR 被广泛用于模块化与组件化开发。
1.1 HAR 的核心优势
- 代码复用:公共逻辑提取到 HAR,多个模块共享
- 独立编译:每个 HAR 可独立编译,加速构建
- 版本管理:通过 oh-package.json5 控制版本
- 资源隔离:资源文件跟随 HAR 打包,不与其他模块冲突
二、项目中的 HAR 模块划分
2.1 Commons 公共层(3 个 HAR)
commons/
├── commonLib/ ← 公共工具库(har)
│ ├── src/main/ets/constants/ ← 常量、枚举
│ ├── src/main/ets/model/ ← 公共数据模型
│ ├── src/main/ets/utils/ ← 工具类
│ └── src/main/ets/push/ ← 推送工具
├── datasource/ ← 数据源服务(har)
│ ├── src/main/ets/ExamService.ets ← 考试服务
│ └── src/main/ets/Model.ets ← 数据模型
└── network/ ← 网络模块(har)
├── src/main/ets/apis/ ← API 接口
├── src/main/ets/mocks/ ← Mock 数据
├── src/main/ets/models/ ← 网络请求封装
└── src/main/ets/types/ ← 类型定义
2.2 Components 组件层(10+ 个 HAR)
每个组件都是一个独立的 HAR 包,拥有自己的构建配置和依赖管理:
// components/exam/oh-package.json5
{
"name": "exam",
"version": "1.0.0",
"dependencies": {
"@ohos_agcit/driver_license_exam_commonlib": "file:../../commons/commonLib",
"@ohos_agcit/driver_license_exam_datasource": "file:../../commons/datasource"
}
}
三、HAR 的创建与配置
3.1 构建配置文件
每个 HAR 都有独立的 build-profile.json5 配置文件:
{
"apiType": "stageMode",
"buildOption": {
"arkOptions": {
"compile ArkTS": true
}
}
}
3.2 模块导出(Index.ets)
每个 HAR 通过 Index.ets 文件对外暴露接口:
// commons/commonLib/Index.ets
export { CommonConstants } from './src/main/ets/constants/CommonContants';
export { CommonEnums } from './src/main/ets/constants/CommonEnums';
export { Logger } from './src/main/ets/utils/Logger';
export { PermissionUtil } from './src/main/ets/utils/PermissionUtil';
export { AccountUtil } from './src/main/ets/utils/AccountUtil';
export { PreferencesUtil } from './src/main/ets/utils/PreferencesUtil';
export { RouterModule } from './src/main/ets/utils/RouterModule';
export { CommonModel } from './src/main/ets/model/CommonModel';
export { PushUtils } from './src/main/ets/push/PushUtils';
3.3 外部引用
在 entry 模块的 oh-package.json5 中声明依赖:
// products/entry/oh-package.json5
{
"dependencies": {
"exam": "file:../../components/exam",
"aggregated_ads": "file:../../components/aggregated_ads",
"aggregated_share": "file:../../components/aggregated_share",
"app_setting": "file:../../components/app_setting",
"feedback": "file:../../components/feedback",
"module_city_select": "file:../../components/module_city_select",
"@ohos_agcit/driver_license_exam_commonlib": "file:../../commons/commonLib",
"@ohos_agcit/driver_license_exam_datasource": "file:../../commons/datasource"
}
}
四、核心 HAR 模块深度解析
4.1 commonLib——公共工具库
commonLib 是最基础的 HAR 模块,提供所有模块都需要的工具类:
// Logger 日志工具类
export class Logger {
private static _domain: number = 0xff00;
private static _prefix: string = 'EmptyTemplate';
private static _format: string = '%{public}s, %{public}s';
public static debug(...args: string[]): void {
hilog.debug(Logger._domain, Logger._prefix, Logger._format, args);
}
public static info(...args: string[]): void {
hilog.info(Logger._domain, Logger._prefix, Logger._format, args);
}
public static error(...args: string[]): void {
hilog.error(Logger._domain, Logger._prefix, Logger._format, args);
}
}
// PreferencesUtil 首选项工具类
export class PreferencesUtil {
private static preferencesUtil: PreferencesUtil;
private static readonly MY_STORE: string = 'myStore';
public static getInstance(): PreferencesUtil {
if (!PreferencesUtil.preferencesUtil) {
PreferencesUtil.preferencesUtil = new PreferencesUtil();
}
return PreferencesUtil.preferencesUtil;
}
getPreferences(context: Context): preferences.Preferences {
preferences.removePreferencesFromCacheSync(context, MY_STORE);
return preferences.getPreferencesSync(context, { name: MY_STORE });
}
preferencesPut(preferences: preferences.Preferences, key: string, value: preferences.ValueType): void {
preferences.putSync(key, value);
this.preferencesFlush(preferences);
}
}
4.2 datasource——数据源服务
datasource 模块封装了考试相关的数据逻辑,对外暴露 ExamService 和各类数据模型:
// ExamService 数据服务单例
@ObservedV2
export class ExamService {
private static _instance: ExamService;
private examDetails: ExamDetail[] = [];
@Trace mockExamCount: number = 0;
@Trace mockExamScore: number[] = [];
public static instance(context: Context) {
ExamService.context = context;
if (!ExamService._instance) {
ExamService._instance = new ExamService();
}
return ExamService._instance;
}
// 获取全部已做数量
public getDidCount(): number {
return this.examDetails.filter(item => item.isCorrect !== undefined).length;
}
// 计算正确率
public calAccuracyRate(): number {
const rightCount = this.getCorrectCount();
const totalCount = this.getTotalCount();
if (rightCount === 0) return 0;
return Math.ceil(rightCount / totalCount * 100);
}
}
4.3 network——网络模块
network 模块封装了基于 Axios 的网络请求:
// AxiosHttpModel 网络请求封装
export class AxiosHttpModel {
private _instance: AxiosInstance;
private _openMock: boolean;
constructor(config: HttpRequestConfig, openMock: boolean = false) {
this._config = config;
this._instance = axios.create(config);
this._openMock = openMock;
this._setupInterceptor();
}
public async request<T = ESObject>(config: HttpRequestConfig): Promise<T> {
return new Promise<T>((resolve, reject) => {
this._instance
.request<ESObject, T>(config)
.then(res => resolve(res))
.catch(err => {
Logger.error(`https request failed:${config.url}`, err.message);
reject(err);
});
});
}
private _setupInterceptor(): void {
this._instance.interceptors.request.use(
this._config.interceptorHooks.requestInterceptor,
this._config.interceptorHooks.requestInterceptorCatch,
);
this._instance.interceptors.response.use(
this._config.interceptorHooks.responseInterceptor,
this._openMock ? this._replaceMock : this._config.interceptorHooks.responseInterceptorCatch,
);
}
}
五、组件 HAR 的独立开发与测试
5.1 独立运行的组件
每个组件 HAR 可以独立开发和测试,通过 BuildProfile 配置不同的运行环境:
// components/exam/BuildProfile.ets
// 编译时区分组件独立运行和作为 HAR 依赖的场景
5.2 组件测试
每个 HAR 都包含独立的测试目录:
components/exam/
├── src/ohosTest/ ← 集成测试
└── src/test/ ← 单元测试
├── List.test.ets
└── LocalUnit.test.ets
六、HAR 模块的最佳实践
6.1 依赖管理原则
- 单向依赖:commons → components → products,避免循环依赖
- 接口抽象:通过 Index.ets 严格控制导出内容
- 版本对齐:多个模块依赖同一 HAR 时使用相同版本
6.2 模块划分原则
- commonLib:纯工具类,无业务逻辑
- datasource:数据层,只关心数据不关心 UI
- network:网络层,只关心通信不关心业务
- components:业务组件,包含 UI 和业务逻辑
七、总结
通过 HAR 模块化设计,DriverLicenseExam 项目实现了:
- 高内聚低耦合:每个 HAR 职责单一,模块间依赖清晰
- 并行开发:团队可以同时开发不同 HAR 模块
- 独立测试:每个 HAR 可独立编译和运行测试
- 按需集成:产品层可以灵活选择需要的组件
这种架构设计是鸿蒙中大型应用的推荐实践,值得学习和借鉴。
关键源码文件:
commons/commonLib/Index.ets— 公共库导出commons/commonLib/src/main/ets/utils/PreferencesUtil.ets— 首选项工具commons/datasource/src/main/ets/ExamService.ets— 数据服务commons/network/src/main/ets/models/AxiosHttpModel.ets— 网络封装products/entry/oh-package.json5— 依赖配置
更多推荐




所有评论(0)