鸿蒙中 HAR和HSP的使用

HAR 和 HSP 都是鸿蒙(HarmonyOS)中用于代码和资源复用的共享包,核心区别在于:HAR 是“静态”的,会在编译时被打包进每一个引用它的模块中,导致代码重复;而 HSP 是“动态”的,在运行时只存在一份实例,能被多个模块共享。
这个区别,导致它们在编译、运行、使用场景上都有很大不同。
HAR vs HSP
| 对比维度 | HAR (静态共享包) | HSP (动态共享包) |
|---|---|---|
| 编译与打包 | 静态打包:代码和资源会随引用方一起编译,每个引用它的 HAP 或 HSP 都独立拥有一份副本。 | 独立编译:自身编译成一个独立的包,运行时供其他模块使用。 |
| 运行时加载 | 加载效率高:代码已存在于引用方包中,启动时已在内存,可直接调用。 | 按需加载:需要额外的查找、加载和初始化过程,会带来一定运行时开销。 |
| 内存与包体积 | 可能导致包体积膨胀:多个模块引用同一 HAR,会造成多份代码和资源的重复拷贝,增大应用包体积。 | 节省内存和空间:多个模块共享同一份 HSP 实例,能有效减少包体积和内存消耗。 |
| 共享能力 | 状态不共享:不同模块引用同一个 HAR,它们获得的只是各自的副本,无法共享状态(如单例对象)。 | 支持数据共享:同一进程内,所有模块共享同一个 HSP 实例,天然支持单例模式和数据共享。 |
| 发布范围 | 可跨应用共享:可以打包发布到 OHPM 私仓或中心仓,供公司内部或全网的其他应用使用。 | 仅限应用内共享:目前主要支持应用内共享,随应用一起打包,不能独立发布供其他应用使用。 |
| 循环依赖与传递 | 不支持依赖传递和循环依赖:A 依赖 B,B 依赖 C,A 不能直接使用 C 的能力;同时 A->B->A 这种循环依赖会直接导致编译报错。 | 不支持依赖传递和循环依赖:与 HAR 一样,也不支持依赖传递和循环依赖,但其依赖管理更复杂,无法像 HAR 那样通过外部转移依赖来规避。 |
pages 页面支持 |
不支持 pages 页面跳转。 |
支持 pages 页面跳转。 |
到底该用谁呢?
-
使用 HAR 的场景:当代码需要跨应用复用时(例如,开发一个通用的网络库、UI 组件库),或者只在一个模块内被引用,无需跨模块共享状态时,HAR 是首选。它的边界简单,调试成本低,非常适合作为基础库。
-
使用 HSP 的场景:当App 有多个模块(HAP),并且它们都需要共享同一套稳定的公共能力(如账户模块、支付模块、核心工具库),或者需要共享较大的资源文件、Native 库,甚至需要在模块间共享数据状态时,应该优先考虑 HSP。它能有效减小包体积,并解决状态共享问题。
比如:
1、工具类 → 用 HAR
工具类 = 纯函数 + 无状态(比如 StringUtils.isEmpty(""))
-
调用不依赖任何上下文
-
输入固定,输出固定
-
不需要保留任何数据
这类代码用 HAR 就对了,每个 HAP 各有一份,互不干扰,不用考虑运行时依赖,也不会有版本冲突。
2、登录模块 → 用 HSP
登录模块不仅仅是一堆函数,它包含了状态(登录状态、用户信息、Token),登录状态是需要被多个业务 HAP 共享的。
比如:
-
在
首页 HAP里登录 →登录状态 = true,用户名 = '张三' -
切换到
个人中心 HAP时,如果它是用 HAR 引入的登录模块,它会拿到另一份独立的登录状态,不知道刚刚登录了,会认为还没登录 → 出问题
HSP 可以在运行时让多个 HAP 共享同一份内存实例。在首页修改了状态,个人中心马上就能感知到,数据保持一致。
说明:
也可以把 “登录模块” 拆成两部分:
-
接口定义 + 数据结构(纯声明,无状态) → 放 HAR,谁用谁引用
-
实现 + 状态管理(有状态) → 放 HSP,保证全局只有一个实例
这样调用方不直接依赖实现,只依赖接口定义,后面替换实现(比如换登录方式)不影响调用方代码,解耦更彻底。
其实 HAR 是“复制粘贴”:每个模块各用各的,互不影响。HSP 是“共享内存”:多个模块共用一份数据,状态互通。工具类用 HAR,业务模块(登录、用户信息、购物车)用 HSP。
更多推荐


所有评论(0)