鸿蒙6.0应用开发——模块化设计选型:HAP、HAR、HSP?
模块化在HarmonyOS中超越简单的代码分解,它是一种为多设备协同与团队并行开发量身定制的架构哲学。其核心在于通过**契约化接口**,将应用拆分为可独立开发、测试、部署的功能单元。这不仅提升了代码的可维护性,更重要的是为应用的**按需分发**与**跨设备能力流转**提供了基石。
【高心星出品】
文章目录
模块化设计选型:HAP、HAR、HSP?
模块化设计:面向分布式生态的工程范式
模块化在HarmonyOS中超越简单的代码分解,它是一种为多设备协同与团队并行开发量身定制的架构哲学。其核心在于通过契约化接口,将应用拆分为可独立开发、测试、部署的功能单元。这不仅提升了代码的可维护性,更重要的是为应用的按需分发与跨设备能力流转提供了基石。
例如,一个"智能家居中心"应用可以被拆分为设备控制、场景自动化、能源管理等多个模块。在手机上,用户可能安装所有模块以进行全功能管理;在手表上,或许只安装"快捷控制"模块;在智慧屏上,则可能侧重"场景可视化"模块。同一应用在不同设备上呈现不同形态,正是通过模块化组合实现的。

UIAbility组件:任务形态决定模块边界
UIAbility是应用模块的前端载体和用户任务的实体。一个关键的设计决策在于:应用是否需要支持多任务并行或多窗口独立操作。
- 独立入口原则:如果某个功能需要作为独立的任务存在,允许用户并行操作(如同时编辑多个文档,或边导航边查询信息),那么它就应当被设计为独立的UIAbility,并通常承载于一个独立的Feature HAP中。
- 扩展能力分离:对于卡片、分享等由ExtensionAbility承载的扩展功能,它们虽无独立界面,但因其独立性和可选择性,也建议放入单独的Feature HAP。这使得用户可以选择不安装这些非核心功能,实现真正的按需加载。
设计初期,应将应用的功能映射为具体的用户任务,这直接决定了工程结构是简单的单HAP模型,还是需要支持灵活组合的多HAP模型。
例如在手机设备上:
- 笔记应用,可让用户将信息从笔记的一页复制到另一页。
- 文档编辑应用,可让用户同时打开编辑多个文档,可让用户将内容从一个文档复制或移动到另一个文档。
- 导航/打车应用,可以让导航后台运行,回到主页查找新的位置信息或其它信息。
- 购物类临时客服界面,可让用户通过任务管理快速从商品浏览页切换回到客服会话界面,避免用户一层层打开查找。
- 在应用支付/登录页面,用户可以切换到其他页面查找并复制相关信息。
模块化三元选型:HAR、HSP与HAP的权衡之道
模块化落地取决于对三种核心模块类型的精准运用,它们构成了一个清晰的决策矩阵:
| 模块类型 | 核心价值 | 关键考量 | 决策指引 |
|---|---|---|---|
| HAR (静态共享包) | 代码与资源复用。 | 复用便利性与包体积膨胀的矛盾。 | 是否需跨应用共享? 是则必选HAR。但需注意,被多个HAP/HSP依赖的HAR会被重复打包,增加总体积。 |
| HSP (动态共享包) | 代码资源复用且仅存一份,节省空间。 | 用性能换取体积。动态加载带来额外开销。 | 是否有大量公共代码被多个可独立部署模块(HAP)复用? 是则考虑HSP,以一次加载开销换取整体包体积的显著缩减。 |
| HAP (部署单元) | 可独立安装、运行,是能力的物理载体。 | 功能独立性与工程复杂度的平衡。 | 该模块是否需要独立入口或能作为独立任务运行? Entry HAP是主入口,Feature HAP是可选的独立功能包。 |
深入分析"多模块引用相同HAR"问题:此问题揭示了HAR静态链接的本质缺陷。当多个HAP或HSP依赖同一HAR时,每个包内部都有一份该HAR代码的副本。这导致:
- 单例失效:每个副本拥有自己的静态变量,破坏全局单例假设。
- 体积膨胀:相同代码被多次存储。
- 启动性能叠加:如果HAR包含初始化逻辑(如示例中的
func()),该逻辑会在每个依赖模块加载时都执行一次,拖慢启动速度。

优化本质:将公共HAR改为HSP,变"静态复制"为"动态链接"。这牺牲了少许加载性能,但换取了体积的节约和运行时状态的唯一性。这是一个经典的工程权衡。

工程结构:在性能与体积间寻找最佳平衡点
单HAP工程:简单应用的精细化取舍
对于多数应用,这是起点。核心抉择在于对"按需加载模块"的优化方向:
- 体积优先模式:当公共依赖库较大时,采用"HSP模块壳"包装。HAP_A和HSP_B共同依赖一个
common_hsp,该HSP内部包含公共库har_C和har_D。这确保了磁盘上只存一份公共代码,但引入了额外HSP的加载开销。

- 性能优先模式:当公共库较小时,让HAP_A和HSP_B直接依赖公共HAR。这避免了动态加载损耗,启动更快,但以安装包体积的轻微增加为代价。

多HAP工程:复杂应用的架构设计
适用于功能聚合型应用。其挑战在于管理多个Feature HAP间错综复杂的公共依赖。
- “模块壳”(Wrapper HSP)的设计智慧:这是应对多HAP公共依赖的优雅方案。
common_wrap_hsp这类模块本身并无业务逻辑,它作为一个"容器",在编译时将多个HAP共用的HAR集合起来,打包成一个独立的HSP。

编译产物中,多个HAP之间存在相同的HAR包(如har_2、har_3、har_C、har_D、har_E)。这种情况下,App Size可能会增大。如果App Size不是应用的瓶颈,或者HAR包的大小较小,对App Size的影响可控,可以采用这种模型,从而减少动态加载的性能损耗

如上图所示,有3个HAP包(1个entry和2个feature),将公共的HAR包封装到HSP工程中,例如common_wrap_hsp和feature_wrap_hsp。这两个HSP从严格意义上讲,不能称为模块,仅称为模块壳,用于合理放置模块在编译产物中的位置,不具备模块功能,不能共享,仅能在App应用内使用,依赖这些模块壳的模块也无法在应用间共享。
- 目的与代价:其唯一目的是消除HAR的重复打包,最小化最终应用体积。然而,每增加一个HSP"壳",就增加了一次动态加载的开销。因此,此模式需谨慎使用,模块壳数量不宜过多,应在体积收益与性能损耗间取得平衡。
性能对比:优化前后的实际效果
通过具体的性能测试数据,我们可以清楚地看到模块化选型对应用性能的实际影响:

图:优化前,使用HSP包时的启动性能分析

图:优化后,使用HAR代替HSP时的启动性能分析
| 优化方案 | 阶段时长(毫秒) | 性能提升 |
|---|---|---|
| 使用HSP包(优化前) | 3125 | - |
| 使用HAR代替HSP(优化后) | 853.9 | 提升72.7% |
表:模块化优化前后的启动性能对比
总结
HarmonyOS模块化是一个系统性工程决策过程,其精髓可归纳为:
- 由外而内设计:首先从用户视角和任务形态出发,用UIAbility划分独立功能入口,确定Feature HAP的边界。
- 由内而外复用:在HAP内部,将可复用的代码与资源抽离为HAR。若该HAR有潜力被其他应用使用,则应将其工程独立,并通过OHPM仓发布。
- 全局权衡优化:最后,俯瞰整个工程结构。若多个HAP依赖相同的大体积HAR群,导致预估包体积超标,则引入HSP(或"模块壳"HSP)作为体积优化器,并坦然接受其带来的微量性能开销。
最终,优秀的模块化设计是在功能独立、代码复用、启动速度、安装包体积这多个维度间,为你的特定应用找到的最优解。它没有固定答案,只有基于深刻理解的持续权衡。
更多推荐




所有评论(0)