1. HarmonyOS项目架构设计中的分层策略
在HarmonyOS应用开发过程中,合理的架构分层直接影响着项目的可维护性和扩展性。共用层(Common Layer)与形态模型(Form Model)的拆分本质上是对业务逻辑与设备适配逻辑的解耦过程。这种分层方式源于分布式能力的核心设计理念——一次开发,多端部署。
共用层通常包含三类核心内容:
- 基础服务模块(账号系统、网络请求、数据持久化)
- 业务领域模型(订单系统、用户资料等核心业务对象)
- 通用工具库(日期处理、字符串工具等跨平台组件)
形态模型则负责处理不同设备的差异化表现:
- 手机端的底部导航栏交互
- 手表端的圆形屏幕适配
- 平板的大屏分栏布局
- 智慧屏的远程控制特性
关键认知:共用层代码应当做到完全设备无感知,任何与具体设备形态相关的判断都应上浮到形态模型层处理。实践中常见错误是在共用层使用
DeviceInfo等API做设备判断,这会导致架构污染。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 项目结构拆分实操指南
2.1 标准目录结构规划
推荐采用以下物理目录划分(以API 9+为例):
code复制project/
├── common/ # 共用层
│ ├── src/main/ets/
│ │ ├── model/ # 领域模型
│ │ ├── service/ # 公共服务
│ │ └── utils/ # 工具库
├── form/ # 形态模型
│ ├── phone/ # 手机形态
│ ├── tablet/ # 平板形态
│ └── wearable/ # 穿戴形态
└── entry/ # 主模块
2.2 依赖关系配置技巧
在oh-package.json5中需要明确声明模块依赖:
json复制{
"dependencies": {
"@common": "file:../common",
"@form-phone": "file:../form/phone"
}
}
通过ohpm安装时添加--legacy-peer-deps参数可避免多模块间的依赖冲突问题。实测在API 9环境下,需要显式指定每个形态模块对共用层的依赖版本。
3. 代码层面的解耦实践
3.1 接口抽象最佳实践
在共用层定义设备无关的抽象接口:
typescript复制// common/src/main/ets/service/AuthService.ets
export abstract class AuthService {
abstract login(credential: Credential): Promise<UserInfo>;
}
在形态层提供具体实现:
typescript复制// form/phone/src/main/ets/service/PhoneAuthService.ets
import { AuthService } from '@common'
export class PhoneAuthService extends AuthService {
override async login(credential: Credential) {
// 手机端特有的生物识别登录逻辑
const result = await biometricAuth(credential);
return this.parseUserInfo(result);
}
}
3.2 状态管理方案选型
推荐采用分层状态管理方案:
- 共用层维护核心业务状态(Redux-like方案)
- 形态层管理UI相关状态(Observable方案)
typescript复制// common/src/main/ets/store/UserStore.ets
class UserStore {
private currentUser: User | null = null;
@State
get isLoggedIn(): boolean {
return this.currentUser !== null;
}
}
// form/tablet/src/main/ets/store/UITabletStore.ets
class UITabletStore {
@State
currentSplitRatio: number = 0.3;
}
4. 构建配置优化方案
4.1 模块化编译配置
在build-profile.json5中配置差异化构建:
json复制{
"targets": [
{
"name": "phone",
"compileMode": "esmodule",
"dependencies": [
"@common",
"@form-phone"
]
}
]
}
4.2 资源文件管理策略
共用资源与形态资源分开存放:
code复制resources/
├── common/ # 共用资源
│ ├── fonts/
│ └── base_icons/
└── form/
├── phone/ # 手机形态资源
│ ├── drawable/
│ └── media/
└── tablet/ # 平板形态资源
在resourceManager.ets中实现资源加载代理:
typescript复制function loadResource(resId: string) {
const form = getCurrentForm();
try {
return formResourceManager.load(resId);
} catch {
return commonResourceManager.load(resId);
}
}
5. 典型问题排查手册
5.1 循环依赖检测
使用ohpm的依赖分析命令:
bash复制ohpm ls --depth=5
常见症状:模块A依赖B,B又反向依赖A。解决方案是提取公共部分到新模块C。
5.2 版本冲突解决
在oh_modules目录下执行:
bash复制ohpm install --legacy-peer-deps --force
特别注意:当共用层与形态模型同时依赖某个三方库时,建议在根项目的oh-package.json5中统一声明版本。
5.3 动态加载失效
设备形态判断的正确姿势:
typescript复制import { FormManager } from '@system.app';
const form = FormManager.getCurrentForm();
// 避免使用deviceInfo获取形态
6. 性能优化专项
6.1 编译时优化
在build-profile.json5中启用作用域提升:
json复制{
"buildOption": {
"treeShaking": true,
"scopeHoisting": true
}
}
实测可减少约15%的包体积,特别对多形态项目效果显著。
6.2 运行时优化
形态模型按需加载方案:
typescript复制async function loadFormModule() {
const form = getCurrentForm();
const module = await import(`@form-${form}`);
return module.createInstance();
}
配合@Prefetch装饰器实现预加载:
typescript复制@Prefetch({ modules: ['@form-phone', '@form-tablet'] })
class AppEntry {
// ...
}
7. 测试策略设计
7.1 共用层单元测试
采用分层测试策略:
typescript复制// common/test/ets/AuthService.test.ets
describe('AuthService', () => {
it('should validate credential format', () => {
const service = new MockAuthService();
expect(service.validate('wrong')).toBeFalsy();
});
});
7.2 形态模型集成测试
使用@ohos.application.testRunner进行设备形态测试:
typescript复制const testRunner = require('@ohos.application.testRunner');
testRunner.register({
onPrepare: (form) => {
console.log(`Testing on ${form} form`);
}
});
8. 持续集成方案
8.1 多形态并行构建
在GitHub Actions中配置矩阵策略:
yaml复制jobs:
build:
strategy:
matrix:
form: [phone, tablet, wearable]
steps:
- run: ohpm build --form=${{ matrix.form }}
8.2 差分打包技术
使用app pack命令生成形态专属包:
bash复制ohos-app pack --form=phone --output=dist/phone
通过--exclude-modules参数可以排除不必要的形态模块。
9. 架构演进建议
9.1 渐进式拆分策略
对于存量项目推荐采用四步走:
- 创建
common模块,迁移纯业务逻辑 - 提取设备相关API到
form接口 - 实现各形态具体适配
- 重构entry模块为轻量级入口
9.2 微前端化探索
在API 10+可以考虑使用@ohos.web.webview实现模块动态加载:
typescript复制const webview = new WebView();
webview.loadModule('@form-phone');
这种方案适合超大型应用的多团队协作场景。
10. 工具链推荐
10.1 代码分析工具
ohpm audit:依赖安全检查arkts-analyzer:架构依赖可视化ohos-hvigor:构建性能分析
10.2 调试技巧
在config.json中开启多形态调试:
json复制{
"deviceTypes": ["phone", "tablet"]
}
使用hdc命令快速切换形态:
bash复制hdc shell param set persist.form.type 2 # 切换为平板形态
