当前位置: 首页 > news >正文

HarmonyOS《柚兔学伴》项目实战02-多模块架构设计与 HSP/HAR 模块化

多模块架构设计与 HSP/HAR 模块化

在 HarmonyOS 应用开发中,随着业务复杂度的增长,单模块工程往往难以满足代码组织、团队协作和构建效率的需求。柚兔学伴项目采用了多模块架构,将不同业务和基础设施拆分为独立模块,实现了清晰的职责划分与灵活的依赖管理。本文将深入剖析 HarmonyOS 的模块体系以及柚兔学伴的模块化实践。

一、HarmonyOS 模块类型

HarmonyOS 提供了三种模块类型,适用于不同场景:

类型全称编译方式运行时共享适用场景
Entry入口模块独立编译为 HAP仅自身使用应用主模块,包含 UIAbility
HSPHarmony Shared Package动态共享包运行时单实例共享多模块共享代码,减小包体积
HARHarmony Archive静态共享包编译时拷贝到各模块三方库、简单共享逻辑

HSP 与 HAR 的核心区别

HSP(动态共享包)在应用运行时只加载一份实例,多个模块引用同一 HSP 时共享同一份代码和资源,因此可以有效减小应用安装包体积。但 HSP 不支持独立发布,只能随应用一起打包。

HAR(静态共享包)在编译时会被完整拷贝到每个依赖它的模块中。如果多个模块引用同一个 HAR,每个模块都会包含一份副本,包体积会增大。HAR 的优势在于支持独立发布到三方库市场,且编译隔离性更好。

选择原则:内部共享模块优先用 HSP,三方库或简单工具用 HAR

二、柚兔学伴的模块拆分

柚兔学伴将项目拆为以下模块:

StudyPartner/ ├── entry/ # 入口模块(HAP) ├── common/ # 基础共享模块(HAR) ├── network/ # 网络请求层(HAR) ├── feature/ │ ├── todo/ # 待办/学习任务模块(HAR) │ ├── stroke/ # 笔画/书写模块(HAR) │ ├── chat/ # AI 对话模块(HAR) │ └── my/ # 个人中心模块(HAR) ├── cloud_objects/ # 云对象模块(HAR) └── smartxplayer/ # 播放器模块(HAR)

模块职责划分:

  • common:全局基础能力,包括通用常量、日志工具、窗口工具、断点系统、路由管理、数据库、通用 UI 组件(TopBar、LoadingView、IconText、TimerComponent)等
  • network:HTTP 请求封装,包含 HttpManager、ApiHttpManager、URL 常量、响应模型
  • feature/todo:学习任务管理,诗词、课本、PDF 阅读
  • feature/stroke:笔画书写练习
  • feature/chat:AI 智能对话
  • feature/my:个人中心、积分、设置、关于

三、oh-package.json5 依赖配置

模块间的依赖关系通过每个模块的oh-package.json5声明。本地模块引用使用"file:"协议,指向相对路径。

entry 模块的依赖

entry 作为入口,依赖所有业务模块:

// entry/oh-package.json5 { "name": "entry", "version": "1.0.0", "dependencies": { "common": "file:../common", "stroke": "file:../feature/stroke", "todo": "file:../feature/todo", "my": "file:../feature/my", "chat": "file:../feature/chat", "cloud_objects": "file:../cloud_objects" } }

feature 模块的依赖

业务模块依赖 common 和 network:

// feature/chat/oh-package.json5 { "name": "chat", "version": "1.0.0", "main": "Index.ets", "dependencies": { "common": "file:../../common", "network": "file:../../network" } }
// feature/todo/oh-package.json5 { "name": "todo", "version": "1.0.0", "main": "Index.ets", "dependencies": { "common": "file:../../common", "network": "file:../../network", "@qtfm/smartxplayer": "file:../../smartxplayer" } }

network 模块的依赖

network 只依赖 common:

// network/oh-package.json5 { "name": "network", "version": "1.0.0", "main": "Index.ets", "dependencies": { "common": "file:../common" } }

依赖方向规则:entry → feature → network → common,形成单向依赖链,避免循环依赖。

四、Index.ets 统一导出设计

每个模块通过根目录的Index.ets文件统一导出对外 API,其他模块只需引用模块名即可使用。

common/Index.ets

common 作为基础层,导出量最大:

// common/Index.etsexport{CommonConstants,Role}from'./src/main/ets/constant/CommonConstants';export{AgentConstant}from'./src/main/ets/constant/AgentConstant';export{ColumnEnum,LoadingStatus,ModuleNameEnum,ScrollDirectionEnum,ProductSeriesEnum,}from'./src/main/ets/constant/CommonEnums';export{defaultasLogger}from'./src/main/ets/util/Logger';export{IPageContext,PageContext}from'./src/main/ets/routermanager/PageContext';export{WindowUtil,StatusBarColorType,ScreenOrientation}from'./src/main/ets/util/WindowUtil';export{BaseState}from'./src/main/ets/viewmodel/BaseState';export{BaseVM}from'./src/main/ets/viewmodel/BaseVM';export{BaseVMEvent}from'./src/main/ets/viewmodel/BaseVMEvent';export{PreferenceManager}from'./src/main/ets/storagemanager/PreferenceManager';export{TodoItem,TodoDatabase}from'./src/main/ets/manager/TodoDatabase';export{GiftExchange,GiftExchangeDatabase}from'./src/main/ets/manager/GiftExchangeDatabase';export{BreakpointTypeEnum,GlobalInfoModel}from'./src/main/ets/model/GlobalInfoModel';export{ProcessUtil}from'./src/main/ets/util/ProcessUtil';export{DbUtil}from'./src/main/ets/util/Dbutil';export{RecordUtils}from'./src/main/ets/util/RecordUtils';export{GlobalUIAbilityContext}from'./src/main/ets/util/ContextConfig';export{PoemReader}from'./src/main/ets/util/PoemReader';export{BreakpointSystem,BreakpointType}from'./src/main/ets/util/BreakpointSystem';// UI 组件export{TopNavigationData,TopNavigationView}from'./src/main/ets/component/TopNavigationView';export{CardItem}from'./src/main/ets/component/CardItem';export{TimerComponent,TimerComponentController}from'./src/main/ets/component/TimerComponent';export{CustomImageToggle}from'./src/main/ets/component/CustomImageToggle';export{IconText}from'./src/main/ets/component/IconText';export{TopBar}from'./src/main/ets/component/TopBar';export{LoadingView}from'./src/main/ets/component/LoadingView';export{BackupManagerService}from'./src/main/ets/manager/BackupManagerService';// 数据模型export{AgentInfoData}from'./src/main/ets/data/AgentInfoData';export{ChatData,ChatResponseData,DeltaData}from'./src/main/ets/data/...';export{PoemDatabase,PoemItem}from'./src/main/ets/db/PoemDatabase';

network/Index.ets

// network/Index.etsexport{PostRequest}from'./src/main/ets/HttpRequest';export{HttpManager,RequestOptions}from'./src/main/ets/HttpManager';export{ApiHttpManager}from'./src/main/ets/ApiHttpManager';export{ChatResultData}from'./src/main/ets/ChatResultData';export{CommonResponseModel}from'./src/main/ets/common/CommonResponseModel';export{UrlConstants,LoadingStatus}from'./src/main/ets/common/UrlConstants';

feature 模块导出

各业务模块只导出视图组件,保持接口精简:

// feature/chat/Index.etsexport{ChatHomePage}from'./src/main/ets/view/ChatHomePage';export{ChatView}from'./src/main/ets/view/ChatView';// feature/stroke/Index.etsexport{StrokePage}from'./src/main/ets/view/StrokePage';export{StrokeView}from'./src/main/ets/view/StrokeView';// feature/my/Index.etsexport{MineView}from'./src/main/ets/view/MineView';// feature/todo/Index.etsexport{TodoView}from'./src/main/ets/view/TodoView';

在 entry 的 HomePage 中直接引用:

import{ChatView}from'chat';import{MineView}from'my';import{StrokeView}from'stroke';import{TodoView}from'todo';import{PageContext,GlobalUIAbilityContext}from'common';

五、module.json5 配置

module.json5定义模块的元信息、类型、设备支持和路由等。

Entry 模块配置

// entry/src/main/module.json5 { "module": { "name": "entry", "type": "entry", "mainElement": "EntryAbility", "deviceTypes": ["phone", "tablet", "2in1"], "deliveryWithInstall": true, "pages": "$profile:main_pages", "routerMap": "$profile:router_map", "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ets", "exported": true, "skills": [{ "entities": ["entity.system.home"], "actions": ["ohos.want.action.home"] }] } ], "requestPermissions": [ { "name": "ohos.permission.INTERNET" }, { "name": "ohos.permission.MICROPHONE", "reason": "$string:attention", "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" } } ] } }

关键字段说明:

  • type:"entry"表示入口模块,一个应用只能有一个 entry
  • deviceTypes: 支持的设备类型,phonetablet2in1覆盖全场景
  • pages: 页面路由配置文件引用
  • routerMap: Navigation 路由表引用
  • abilities: 声明的 UIAbility 列表

HAR 模块配置

// feature/chat/src/main/module.json5 { "module": { "name": "chat", "type": "har", "routerMap": "$profile:router_map", "deviceTypes": ["default", "tablet", "2in1"] } }

HAR 模块配置更简洁,无需声明 abilities 和 pages,但可以声明routerMap以支持 Navigation 路由跳转。deviceTypes中的"default"表示支持所有默认设备类型。

六、模块化最佳实践

  1. 依赖方向单向化:严格遵循 entry → feature → network → common 的依赖链,绝不反向依赖
  2. Index.ets 精简导出:只导出其他模块需要使用的 API,内部实现细节不暴露
  3. HAR 与 HSP 选择:当前项目 feature 模块使用 HAR,若多个模块引用同一 feature 且包体积敏感,可迁移为 HSP
  4. routerMap 分模块声明:每个 feature 模块独立维护自己的路由表,entry 模块的路由表会自动合并
  5. common 层保持纯粹:common 不依赖任何业务模块,只提供基础设施能力

小结

柚兔学伴的多模块架构将应用拆分为 entry(入口)、common(基础)、network(网络)和多个 feature(业务)模块,通过oh-package.json5"file:"协议声明本地依赖,通过Index.ets统一导出 API,通过module.json5配置模块类型与能力。这种架构使代码职责清晰、依赖关系明确,为多人协作和持续迭代奠定了坚实基础。

http://www.jsqmd.com/news/1176958/

相关文章:

  • 2026年7月最新沈阳天梭官方售后客户服务热线与维修网点地址汇总 - 天梭服务中心
  • 论文查重免费真的靠谱吗?2026年免费查重网站避坑指南
  • 【高阶·安全】AI 红队测试方法论与自动化安全评测深度解析:从 Garak/Giskard 到企业级对抗测试体系
  • Laguna-XS-2.1-bf16推理优化技巧:10个提升生成速度的实用方法
  • 2026 广东湛江市全区域彩钢瓦修缮公司 TOP4 权威推荐|彩钢瓦翻新 / 防水补漏 / 除锈喷漆优选指南 + 避坑攻略 - 本地便民网
  • “TVA-世界模型”引爆具身智能产业化奇点(4)
  • AI 里面的表格怎么复制?AI 导出鸭安卓版无损保留格式一键导出
  • QEMU 8.2.2 Windows 部署 UOS ARM 虚拟机:3步脚本配置与 SSH 端口 2222 映射
  • 移动端 PGO 优化怎么评估:平均 FPS 没变,为什么 1% Low 更关键?
  • vLLM部署Qwen3.5-397B-A17B-NVFP4最佳实践:8卡GPU配置与高并发优化指南
  • 8款高效护眼终端配色方案:告别视觉疲劳的完整指南
  • 等保测评前夜,改错一条审计规则差点让系统被“一票否决”!我把国产库审计策略做成了“Git化”自动同步与回滚引擎
  • 如何在GTA5线上模式中解锁超乎想象的游戏体验?
  • 2026年5月成都装修公司实测榜:优选六大本土品牌,口碑稳定与施工实力双认证 - 推荐官
  • SUID高级主题:自定义组件、扩展系统、插件开发的完整教程
  • 正则生成已进入“提示词工程+语法感知”双阶段:2024最新Benchmark显示,带AST约束的Prompt使错误率下降73.4%
  • ShellWrap高级用法:流式输出处理与回调函数应用指南
  • 4. 【Java】JVM 的秘密:Java 为什么能“一次编写,到处运行“
  • python数据可视化技巧的100个练习 -- 8. 使用 Python 可视化多个函数
  • 2026 铜川耀州黄金回收规范化盘点:告别小作坊套路,30 年零差评连锁全域免费上门 - 福金阁黄金回收
  • 分享一套锋哥原创的基于Python的会员管理系统(带微信小程序会员端)(FastAPI+Vue3)优质版
  • 2026 龙州黄金回收实地走访:3 大收割套路深度拆解,三大 30 年零差评老牌全城全覆盖免费上门 - 福金阁黄金回收
  • LinkSwift:八大网盘直链下载助手的完整开发者指南
  • 【信息科学与工程学】【通信工程】第七十七篇 城域网+FTTR/FTTB/FTTC/FTTO的数学分析01
  • NVIDIA多模态嵌入模型架构揭秘:Llama 3.2 1B + SigLip2 400M的完美结合
  • 2026年6月成都装修公司排行榜|权威实测评测(覆盖成都全域) - 推荐官
  • 【计算机工具类-协作工具Skills】cal-com-automation 技能
  • unipp中 @tap 运行到小程序,不生效
  • MiniMax-M2.5-NVFP4推理优化技巧:让你的AMD GPU推理速度提升300%
  • 地球物理大地测量学计算系列之十广义Stokes/Hotine数值积分外部高程异常计算