Files
harmony-client/docs/architecture.md

8.9 KiB
Raw Permalink Blame History

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 放宽混合约束。

主要引用:


10. 边界与后续

  • 本次为骨架级交付,未实现真实后端对接与具体业务(保留示例链路)。
  • 未新增 feature HAR(无业务领域),仅写入抽取指南。
  • 未做多设备适配(已确认仅 phone)。
  • 后续待办:token 刷新策略、RDB 持久化、自动化测试基建、环境配置注入(BASE_URL)。