3、项目结构对比:安卓Gradle项目 vs 鸿蒙HAP项目,模块化与多工程管理,资源文件组织方式
说实话,我刚从安卓转到鸿蒙时,第一反应是:这项目结构怎么这么眼熟?但仔细一挖,发现坑还挺多。今天我就把这两套体系掰开揉碎了讲,顺便聊聊我踩过的那些坑。
3.1 整体骨架:Gradle项目 vs HAP项目
安卓用 Gradle 构建,这大家都知道。一个典型项目长这样:
MyAndroidApp/
├── app/
│ ├── build.gradle
│ └── src/
├── library/
│ ├── build.gradle
│ └── src/
├── settings.gradle
└── build.gradle
鸿蒙这边呢?用的是自家的 HAP 包结构。说白了,HAP 就是鸿蒙的应用包,类似安卓的 APK。但组织方式不太一样:
MyHarmonyApp/
├── entry/
│ ├── build-profile.json5
│ └── src/
├── library/
│ ├── build-profile.json5
│ └── src/
├── build-profile.json5
└── oh-package.json5
嗯,这里要注意:鸿蒙没有 Gradle,用的是自家的构建系统。配置文件从 .gradle 变成了 .json5。我个人习惯把 build-profile.json5 看作鸿蒙版的 build.gradle,这样理解起来轻松很多。
核心差异一句话:安卓用 Groovy/Kotlin DSL 写构建脚本,鸿蒙用 JSON5 写配置。前者灵活但复杂,后者简洁但约束多。
3.2 模块化:多 Module vs 多 HAP
安卓里我们经常搞多 Module 工程,比如:
app- 主模块common- 公共库feature_home- 首页模块feature_login- 登录模块
鸿蒙这边呢?叫多 HAP 工程。每个 HAP 就是一个独立的功能单元。我记得第一次迁移时,直接把安卓的 Module 结构照搬过来,结果编译报错——鸿蒙对 HAP 之间的依赖关系有严格限制。
为什么会这样?因为鸿蒙的 HAP 分为两种:
| 类型 | 说明 | 安卓类比 |
|---|---|---|
| Entry HAP | 应用入口,必须有一个 | app Module |
| Feature HAP | 功能模块,按需加载 | feature Module |
| Shared HAP | 共享库,被其他 HAP 引用 | library Module |
你想想看,安卓里 Module 之间可以随便互相依赖,但鸿蒙里 Entry HAP 不能依赖 Feature HAP,只能反过来。这个限制我当初折腾了一下午才搞明白。
我的建议:迁移时先把安卓的 Module 依赖图画出来,然后按鸿蒙的规则重新组织。别硬搬,否则后面改起来很痛苦。
3.3 多工程管理:Gradle Composite Build vs 鸿蒙多工程
大项目里,安卓会用 Composite Build 来管理多个独立工程。鸿蒙也有类似机制,叫多工程管理。
安卓的做法:
// settings.gradle
includeBuild('../shared-library')
includeBuild('../network-library')
鸿蒙的做法:
// build-profile.json5 { "app": { "products": ["phone", "tablet"] }, "modules": [ { "name": "entry", "srcPath": "./entry" }, { "name": "shared", "srcPath": "../shared-library" } ] }我个人觉得鸿蒙的多工程管理更直观一些。你直接在
build-profile.json5里列出所有模块的路径就行,不用像 Gradle 那样搞一堆settings.gradle和includeBuild。不过要注意:鸿蒙的多工程要求所有模块在同一个
oh-package.json5的命名空间下。我曾经把两个不同团队的模块硬凑到一起,结果包名冲突,编译直接挂了。避坑指南:我曾经因为没统一包名,导致 Feature HAP 引用 Shared HAP 时一直报找不到类。检查了半天才发现是 oh-package.json5 里的 name 字段写错了。记住:所有模块的 name 必须唯一,且遵循反向域名规则。
3.4 资源文件组织:res vs resources
这是迁移中最容易出问题的地方。安卓的资源在
res/目录下,鸿蒙的在resources/目录下。名字像,但结构完全不同。安卓的资源结构:
res/ ├── drawable/ ├── layout/ ├── values/ │ ├── strings.xml │ └── colors.xml ├── mipmap/ └── raw/鸿蒙的资源结构:
resources/ ├── base/ │ ├── element/ │ │ ├── string.json │ │ └── color.json │ ├── media/ │ └── profile/ ├── en_US/ │ └── element/ │ └── string.json └── zh_CN/ └── element/ └── string.json嗯,这里有个关键区别:鸿蒙把资源按「用途」和「语言」双重维度组织。
base/是默认资源,en_US/和zh_CN/是国际化资源。安卓是把国际化资源放在values-en/、values-zh/这样的目录里。说白了,鸿蒙的资源组织更「工程化」一些。你想想看,安卓的
drawable-hdpi、drawable-xhdpi这种目录,是不是很烦?鸿蒙直接按media/统一管理,系统自动适配。迁移要点:
- 布局文件:安卓的
.xml布局 → 鸿蒙的.hml或.ets布局- 图片资源:安卓的
drawable/→ 鸿蒙的resources/base/media/- 字符串:安卓的
strings.xml→ 鸿蒙的string.json- 颜色:安卓的
colors.xml→ 鸿蒙的color.json我记得有一次迁移一个老项目,里面用了大量
selector和shape资源。鸿蒙没有这些概念,得用代码实现。那两天我几乎都在写状态管理逻辑,头都大了。3.5 知识体系总览
下面这张图是我自己总结的,帮你快速建立整体认知:
这张图把四个核心维度都列出来了。你对照着看,迁移时心里就有底了。
3.6 迁移实战建议
最后,我总结几条实战经验:
- 先理清模块依赖:把安卓的 Module 依赖图画出来,再按鸿蒙的规则重新设计。别偷懒,这一步省不了。
- 资源文件分批迁移:先迁移字符串和颜色,再迁移布局和图片。每迁移一批就编译一次,别攒到最后一起搞。
- 注意包名一致性:所有 HAP 的
oh-package.json5里的name必须统一命名空间,否则编译报错。- 善用工具:鸿蒙 DevEco Studio 有资源迁移向导,能帮你把安卓的
res/转成鸿蒙的resources/。虽然不能 100% 自动完成,但能省不少事。小技巧:如果你项目里有大量
selector资源,建议写个脚本批量转换。我当初手动改了一百多个文件,手都酸了。后来写了个 Python 脚本,十分钟搞定。好了,项目结构这块就聊到这儿。记住一句话:结构是骨架,搞清楚了骨架,后面的血肉(代码逻辑)才能长对地方。