210 lines
8.9 KiB
Markdown
210 lines
8.9 KiB
Markdown
# HarmonyOS NEXT 客户端 · 架构设计文档
|
||
|
||
> 项目:`harmony-client`(ArkTS + ArkUI,SDK 6.0.2 / API 22,仅 phone)
|
||
> 业务形态:对接自有后端的通用业务客户端(HTTP + 鉴权 + CRUD)
|
||
|
||
---
|
||
|
||
## 1. 背景与目标
|
||
|
||
本工程从 DevEco 空脚手架起步,目标是建立一套**可持续演进、可测试、低耦合**的客户端架构骨架,为后续业务开发打底。设计依据来自一轮 deep-research 调研(交叉验证华为官方文档与社区实践,9 条结论全部通过对抗式验证)。
|
||
|
||
核心决策:
|
||
|
||
| 决策点 | 选择 | 理由 |
|
||
|---|---|---|
|
||
| 工程结构 | 官方三层 commons / features / products | 单向依赖、官方白皮书推荐 |
|
||
| 模块化 | **单 HAP + 多 HAR** | HAR 编译期打包、可裁剪;HSP 仅按需加载 |
|
||
| 代码分层 | **MVVM + 独立 data 层** | 官方指南 + 网络/数据解耦 |
|
||
| 状态管理 | **全量 StateManagement V2** | API 22 下 V2 能力完整,字段级精准刷新 |
|
||
|
||
---
|
||
|
||
## 2. 模块划分与依赖
|
||
|
||
```
|
||
harmony-client/
|
||
├── entry/ HAP 应用壳 + 业务功能(唯一入口,EntryAbility)
|
||
├── common/ HAR 基础设施层(网络 / 日志 / 状态 / 工具,无业务、无 UI 组件)
|
||
└── uikit/ HAR 通用 UI 组件库 + 主题(无业务、无网络依赖)
|
||
```
|
||
|
||
依赖方向严格单向,禁止反向/循环:
|
||
|
||
```
|
||
entry ──依赖──▶ common
|
||
entry ──依赖──▶ uikit
|
||
common / uikit 各自独立,互不依赖
|
||
```
|
||
|
||
- **common**:`HttpClient`、鉴权拦截器、统一错误模型、`Logger`、`SessionStore`(PersistenceV2 持久化)、工具函数。
|
||
- **uikit**:主题 token(`AppColor/AppSpacing/AppFontSize`)、通用组件(`AppButton/LoadingView/EmptyView`)。
|
||
- **entry**:应用壳装配、路由、DI 容器、MVVM 分层业务代码。
|
||
|
||
---
|
||
|
||
## 3. 分层与目录结构(entry 内)
|
||
|
||
采用官方 MVVM 指南的**层优先**结构,叠加独立 `data/` 层与横切的 `router/`、`di/`:
|
||
|
||
```
|
||
entry/src/main/ets/
|
||
├── entryability/
|
||
│ └── EntryAbility.ets # 生命周期装配:Logger / ServiceLocator / SessionStore
|
||
├── router/
|
||
│ ├── RouteMap.ets # 路由名常量 + name→页面 分发
|
||
│ └── AppRouter.ets # Navigation 导航封装(push/replace/pop/...)
|
||
├── di/
|
||
│ └── ServiceLocator.ets # 轻量服务定位器(ArkTS 无反射,手动注册/解析)
|
||
├── model/ # 领域模型:@ObservedV2 + @Trace 实体
|
||
├── data/
|
||
│ ├── api/ # DTO + 请求服务(调 common 的 HttpClient)
|
||
│ └── repository/ # 数据仓库契约(抽象类)+ 实现
|
||
├── viewmodel/ # @ObservedV2 状态容器(data/loading/error 三态)
|
||
├── view/ # 可复用 UI 组件(@ComponentV2)
|
||
└── pages/ # 页面,仅编排(组合 view + viewmodel)
|
||
```
|
||
|
||
**单向数据流**:
|
||
|
||
```
|
||
pages → viewmodel → repository(契约) → api → HttpClient → 后端
|
||
↑ 状态回传由 @Trace 触发自动刷新
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 状态管理约定(全量 V2,禁用 V1)
|
||
|
||
| 场景 | 使用 |
|
||
|---|---|
|
||
| 组件/页面 | `@ComponentV2` |
|
||
| 组件内部状态 | `@Local` |
|
||
| 父→子输入 | `@Param` |
|
||
| 子→父输出/回调 | `@Event`(**不用 `@Link`**;需双向时用 `@Param` 的 `!!` 语法糖) |
|
||
| 类/模型可观察 | `@ObservedV2` 类 + `@Trace` 字段 |
|
||
| 跨层共享 | `@Provider` / `@Consumer` |
|
||
| 变化监听 | `@Monitor` |
|
||
| 全局会话 | `SessionStore`(`@ObservedV2` 单例,见 `common/state/SessionStore.ets`) |
|
||
| 轻量持久化 | `PersistenceV2.globalConnect(...)`;结构化数据后续用 relationalStore(RDB) |
|
||
|
||
**核心约定**:ViewModel 是 `@ObservedV2` 类,持有 `@Trace` 的 `data/loading/error` 三态;页面只读状态、调方法,不直接碰 Repository / 网络层。
|
||
|
||
---
|
||
|
||
## 5. 网络与数据层
|
||
|
||
### 5.1 网络层(`common/src/main/ets/network/`)
|
||
|
||
- `HttpClient`:封装 `@kit.NetworkKit` 的 http,统一超时/请求头,支持**拦截器链**。
|
||
- `HttpInterceptor`:拦截器接口(`onRequest` / `onResponse`)。
|
||
- `AuthInterceptor`:请求前注入 `Authorization: Bearer <token>`;401 时清空会话。
|
||
|
||
### 5.2 鉴权流程
|
||
|
||
```
|
||
请求 → AuthInterceptor.onRequest 注入 token → 发出
|
||
→ AuthInterceptor.onResponse 检查 401
|
||
→ (当前) 清空 SessionStore,由上层跳登录
|
||
→ (TODO) token 刷新 + 原请求重放(防并发刷新),需后端 refresh 接口约定后实现
|
||
```
|
||
|
||
### 5.3 Repository 模式
|
||
|
||
- `data/repository/` 中定义**抽象类契约**,ViewModel 只依赖契约,实现可替换(真实 / mock)。
|
||
- 用抽象类而非 interface,是为了在 `ServiceLocator` 中做 `Object → 契约` 强转时兼容 ArkTS。
|
||
- `data/api/` 返回 DTO,Repository 负责 **DTO → 领域模型** 映射。
|
||
|
||
### 5.4 统一响应与错误
|
||
|
||
- `ApiResult<T>`:`{ code, message, data }`,`code === 0` 为成功。
|
||
- `ApiError`:区分网络异常 / HTTP 状态码 / 业务错误码。
|
||
|
||
---
|
||
|
||
## 6. 横切关注点
|
||
|
||
### 6.1 依赖注入
|
||
|
||
`di/ServiceLocator.ets`:`Map<string, Object>` 单例注册表。启动时在 `EntryAbility.onCreate` 注册 `HttpClient`、各 Repository、`SessionStore`;业务侧 `get(key)` 后强转。
|
||
|
||
> ArkTS 无反射,用字符串 key + 显式强转;若后续规模增大可引入类型安全的 key 常量或轻量注入容器。
|
||
|
||
### 6.2 导航
|
||
|
||
`Navigation` + `NavPathStack`(官方推荐,替代旧 Router)。`RouteMap.ets` 定义路由名常量与 `name→页面` 分发;`AppRouter` 持有全局 `NavPathStack` 提供 `push/replace/pop/popToName/clear`。HAR 不承载路由。
|
||
|
||
### 6.3 日志
|
||
|
||
`common/logging/Logger.ets`:封装 `hilog`,统一 DOMAIN,后续可加等级开关/上报。
|
||
|
||
### 6.4 持久化
|
||
|
||
- `PersistenceV2`:轻量 KV(token / 用户偏好),`@Trace` 字段自动落盘。
|
||
- `relationalStore(RDB)`:结构化数据(订单、列表缓存等),后续引入。
|
||
|
||
---
|
||
|
||
## 7. 编码规范
|
||
|
||
1. **状态管理只用 V2**:新组件一律 `@ComponentV2`,禁止混入 V1 装饰器。
|
||
2. **单向数据流**:父→子用 `@Param`,子→父用 `@Event`;页面不直接改 ViewModel 之外的全局状态。
|
||
3. **页面只编排**:`pages/` 下只做组件组合与 ViewModel 调用,业务逻辑进 ViewModel,数据进 Repository/Api。
|
||
4. **跨模块引用走 `Index.ets`**:entry 只 `import { ... } from 'common'/'uikit'`,不直接引 HAR 内部路径。
|
||
5. **魔法值收敛到 `uikit/theme/Theme.ets`**:颜色/间距/字号统一取 token。
|
||
|
||
---
|
||
|
||
## 8. 演进指南
|
||
|
||
### 8.1 抽取 feature HAR(业务领域明确后)
|
||
|
||
当某个业务领域(如订单、支付)足够独立时,新增 `feature_xxx` HAR:
|
||
|
||
```
|
||
feature_order/
|
||
├── src/main/ets/{model,data,viewmodel,view,pages}
|
||
└── oh-package.json5 (name: feature_order, main: Index.ets)
|
||
```
|
||
|
||
- 根 `build-profile.json5` 的 `modules` 增加该模块。
|
||
- 依赖它的模块在其 `oh-package.json5` 增加 `"feature_order": "file:../feature_order"`。
|
||
- 依赖方向:`entry → feature_xxx → common/uikit`,禁止 feature 之间横向依赖(确实需共享时下沉到 `common`)。
|
||
|
||
### 8.2 迁移到 feature-first
|
||
|
||
当 feature 数量增多、单层目录过深时,可将 `model/data/viewmodel/view/pages` 按 feature 重组:
|
||
|
||
```
|
||
ets/features/<feature>/{model,data,viewmodel,view,pages}
|
||
ets/shared/… # 跨 feature 共享
|
||
```
|
||
|
||
迁移原则:先把稳定边界抽 HAR,再在 HAR 内部做 feature 分组。
|
||
|
||
---
|
||
|
||
## 9. 调研结论摘要与引用
|
||
|
||
- 官方 MVVM(StateManagement V2)指南给出 `model/viewmodel/view/pages` 分层。
|
||
- 官方三层工程结构:commons(禁止反向依赖)/ features / products(不可横向调用),打包形态 HAR/HSP/Feature HAP/Entry HAP。
|
||
- V2 装饰器映射:`@State→@Local`、`@Prop→@Param`、`@Link→@Param+@Event`、`@Observed→@ObservedV2+@Trace`、`@Watch→@Monitor`、`AppStorage→AppStorageV2`、`PersistentStorage→PersistenceV2`。
|
||
- V1/V2 不可混用(编译错误);API 19+ 提供 `UIUtils.enableV2Compatibility/makeV1Observed` 放宽混合约束。
|
||
|
||
主要引用:
|
||
|
||
- https://developer.huawei.com/consumer/en/doc/harmonyos-guides/arkts-mvvm-v2
|
||
- https://developer.huawei.com/consumer/cn/doc/HarmonyOS-Guides/arkts-decorator-overview
|
||
- https://device.harmonyos.com/en/docs/apiref/harmonyos-guides/arkts-v1-v2-update-difference
|
||
- https://github.com/openharmony/docs(arkts-v1-v2-migration-application / mixusage / inner-component)
|
||
- https://github.com/OpeNopEn2007/arkts-patterns
|
||
|
||
---
|
||
|
||
## 10. 边界与后续
|
||
|
||
- 本次为**骨架级**交付,未实现真实后端对接与具体业务(保留示例链路)。
|
||
- 未新增 feature HAR(无业务领域),仅写入抽取指南。
|
||
- 未做多设备适配(已确认仅 phone)。
|
||
- 后续待办:token 刷新策略、RDB 持久化、自动化测试基建、环境配置注入(BASE_URL)。
|