【鸿蒙应用开发实战·食光篇】第五篇:构建优化与发布准备——错误排查与真机部署
【鸿蒙应用开发实战·食光篇】第五篇:构建优化与发布准备——错误排查与真机部署
一、前言
经过四篇的开发,我们完整构建了「食光」美食App——5个页面、10道菜谱、5大菜系,总代码量超过1300行。本篇将介绍构建优化、常见错误排查和发布准备,把项目从开发环境推向可部署状态。
二、hvigor 构建系统深入理解
2.1 构建流程
「食光」项目的构建流程与「阅迹」一致,但编译的文件更多(5个页面 + 1个数据模型):
hvigorw.js
└── hvigor daemon (守护进程)
├── PreBuild → 预处理
├── ProcessProfile → 配置文件合并
├── CompileResource → 资源编译
├── CompileArkTS → ArkTS编译 ← 核心阶段
├── PackageHap → HAP打包
├── SignHap → 签名
└── CollectDebugSymbol → 调试符号
2.2 增量构建与守护进程
启用 daemon 后,二次构建仅需1-3秒:
首次构建:~10秒(全量编译ArkTS)
二次构建:~2秒(仅编译变更文件)
三次构建:~1秒(缓存命中)
通过在命令中添加 --daemon --incremental 参数启用。
三、常见编译错误与解决方案
3.1 Row 的 space 必须用构造函数
错误:
Property 'spacing' does not exist on type 'RowAttribute'
原因:ArkTS 中 Row 没有 .spacing() 方法,space 只能通过构造函数设置。
修复:
// ✅ 正确
Row({ space: 12 }) { ForEach(...) }
// ❌ 错误
Row() { ForEach(...) }.spacing(12)
适用组件:Row、Column、List、Grid 统一使用构造函数传递 space。
3.2 ArkTS 严格模式的对象类型
规则:
arkts-no-untyped-obj-literals → 对象字面量必须显式类型
arkts-no-noninferrable-arr-literals → 数组必须可推断类型
修复:
// ✅ 必须标注类型
const RECIPES: Recipe[] = [{ id: 1, name: '麻婆豆腐', /* ... */ }];
// ✅ Record 类型也需要标注
const map: Record<string, string> = { '初级': '#27AE60' };
3.3 router 的正确导入
// ✅ 正确:API 23 必须从 @ohos.router 导入
import router from '@ohos.router';
// ❌ 错误:@kit.AbilityKit 不导出 router
import { router } from '@kit.AbilityKit';
3.4 getParams 的参数类型转换
router.getParams() 返回 Object 类型,需要强制转换:
const params = router.getParams() as Record<string, Object>;
if (params && params['cuisine']) {
this.currentCuisine = params['cuisine'] as string;
}
3.5 AppStorage 数组同步
@StorageLink 绑定的数组修改后必须手动同步:
// 数组修改后必须手动 set
this.favoriteIds.push(recipeId);
AppStorage.set<number[]>('favoriteIds', this.favoriteIds);
四、代码优化建议
4.1 减少 @State 的使用
不必要的 @State 会导致组件频繁重绘:
// ❌ 不需要响应式
@State private totalCount: number = RECIPES.length;
// ✅ 改用普通属性
private totalCount: number = RECIPES.length;
4.2 ForEach 的 key 生成
提供稳定的 key 可以优化列表渲染:
ForEach(this.filteredRecipes, (item: Recipe) => {
// ...
}, (item: Recipe) => item.id.toString())
4.3 避免 build() 中的重复计算
// ❌ build 中每次渲染都执行计算
build() {
const count = this.favoriteIds.length;
Text(count.toString())
}
// ✅ 用 @State 缓存
@State favCount: number = 0;
aboutToAppear() {
this.favCount = this.favoriteIds.length;
}
五、签名配置与真机部署
5.1 签名配置
在 build-profile.json5 中配置签名信息:
{
"app": {
"signingConfigs": [
{
"name": "default",
"material": {
"certpath": "path/to/release.cer",
"profile": "path/to/release.p7b",
"keystore": {
"storeFile": "path/to/keystore.p12",
"keyAlias": "keyAlias",
"storePassword": "******",
"keyPassword": "******"
}
}
}
]
}
}
5.2 真机安装
# 使用 hdc 工具安装
hdc install -r entry/build/default/output/default/entry-default-signed.hap
5.3 构建产物
entry/build/default/output/default/
├── entry-default-unsigned.hap ← 未签名(模拟器用)
└── entry-default-signed.hap ← 已签名(真机用)
六、项目文件总览
最终「食光」项目的源码统计:
| 文件 | 行数 | 说明 |
|---|---|---|
model/RecipeData.ets |
246行 | 数据模型 + 10道菜谱 + 查询函数 |
pages/Index.ets |
336行 | 首页(菜系入口 + 推荐 + 榜单) |
pages/RecipeListPage.ets |
174行 | 菜谱列表(分类标签 + 卡片) |
pages/RecipeDetailPage.ets |
273行 | 菜谱详情(Tab + 食材+步骤) |
pages/FavPage.ets |
107行 | 收藏页 |
pages/ProfilePage.ets |
137行 | 个人中心 |
| 总计 | 约1273行 | 6个 ArkTS 源文件 |
七、两个系列总结
通过两个完整的鸿蒙原生应用开发项目,我们覆盖了:
基础技能:
- Stage 模型的项目结构
- ArkTS 语法与严格模式
- hvigor 构建系统
- 资源文件管理
UI组件:
- Row/Column 布局
- Scroll/List/ForEach 列表
- Stack 层叠布局
- Button/Text/Divider
- @Builder 组件化
状态管理:
- @State/@Link/@Prop
- AppStorage/@StorageLink
- 数组同步注意事项
路由导航:
- router.pushUrl/back
- 参数传递与接收
- 路由表配置
数据设计:
- 接口定义与类型标注
- 工具函数封装
- 数组型数据(食材/步骤)
- 颜色映射函数
九、下一步扩展建议
- 数据持久化:使用
PersistentStorage或关系数据库,收藏数据重启不丢失 - 图片资源:使用真实菜品图片替代纯色封面
- 搜索功能:用户可按菜名搜索菜谱
- 自动计时器:烹饪步骤中集成计时功能
- 分享功能:通过意图(Want)分享菜谱
- 深色模式:适配深色主题
十、写在最后
五篇连载,两个完整应用——「阅迹」阅读App和「食光」美食App,共计超过2600行ArkTS代码,覆盖了5个页面模式下的绝大部分开发场景。
HarmonyOS 生态正在快速发展,API 23 的 Stage 模型和 ArkTS 语言已经非常成熟。希望这两个实战项目能够帮助正在学习鸿蒙开发的开发者少走弯路,快速上手。
如果你在开发中遇到任何问题,欢迎在评论区留言交流!

#鸿蒙开发 #ArkTS #HAP打包 #真机部署 #构建优化 #移动开发
全文完 | 「食光」鸿蒙原生应用开发实战系列
第一篇:[项目初始化与数据模型]
第二篇:[首页与菜系导航]
第三篇:[菜谱列表与详情页]
第四篇:[收藏功能与个人中心]
第五篇:[构建优化与发布准备]
更多推荐



所有评论(0)