20分钟出原型 · 2小时踩6个坑 · 鸿蒙NEXT真机开发实战
有了 AI 助手之后,一个大胆的想法冒了出来——
是不是可以写一个 APP,用于日常的查询、计算?我是测试工程师,可以在 APP 中增加 GPS 定位功能,显示当前位置、时间、速度、星座。还可以让 APP 覆盖一个人的日常需求, 从衣食住行到吃喝玩乐。以后自己再需要什么功能,就不用看烦人的广告,或者不小心 被摇一摇带到某个购物软件,或者暗自在后台偷偷下崽……
— 高昆,2026年6月24日
HUAWEI Mate 80 · HarmonyOS NEXT 6.1.0 · DevEco Studio · 真机运行效果
在浏览器中模拟APP的完整交互体验
提示词扔给 AI,20 分钟拿到可用网页。5 个 Tab 页面布局、Bento 网格、暖白配色。
AI 输出了一个完整的交互原型 HTML。琥珀橙(#D97706)做主题色,暖白底(#FFFBEB),圆角卡片,底部 5 个 Tab。
| 页面 | 内容 |
|---|---|
| 🏠 首页 | 问候语 + AI助理卡 + GPS/UTC/天气状态卡 + Bento网格 |
| 🛠 工具 | 时间转换 + GPS卫星状态 + Ntrip差分 |
| 🌿 生活 | 吃什么/喝什么/穿什么/住/运动/出行 六宫格 |
| 🎯 智趣 | AI对话 + 象棋/五子棋/围棋 + 音乐 + 视频 + 放松 |
| 👤 我的 | 个人资料 + 口味/运动偏好 + Ntrip授权 + 隐私 + 关于 |
手机接电脑 → 开发者模式 → DevEco Studio → 空项目 → AI 写 ArkTS 代码 → 真机运行。
| 手机 | HUAWEI Mate 80 |
| 系统 | HarmonyOS NEXT 6.1.0.125 SP9 |
| IDE | DevEco Studio |
| API | 12+ |
| Bundle | com.gaokun.assistant |
真机调试中踩过的每一个坑,按发现顺序排列。
Column 组件只有 height(),没有 minHeight()。换成 .height(110) 即可。
同一变量不能同时用两个状态装饰器。用 @Provide('key') 显式 key,拆成独立变量。
ArkTS 禁内联对象类型,必须用 interface 或 class。
数据在变,UI 不更新。这是最坑的一个,花了最多时间排查。
6 种方案全部阵亡。根因:TabContent 子页面的 @State 变更不触发重渲染。
权限已授权、监听已注册,但星数始终 14 颗。和时钟同根因——后台数据变了 UI 不动。
geoLocationManager.on('satelliteStatusChange', ...) — 回调类型错误,编译不通过。
每 3 秒随机抖动北斗 13~15 颗 + GPS 9~11 颗。编译过了但 BusinessError 201 —— 没运行时授权。
回调是单对象 SatelliteStatusInfo,不是数组。字段是 satelliteConstellation。北斗枚举 = 5。
atMgr.requestPermissionsFromUser(this.context, [ 'ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION' ]);
✅ 权限已授权!日志显示 "定位权限: 已授权✅" + "卫星监听已启动"。
所有前置条件都满足了,但星数不更新。高度怀疑 TabContent 内 @StorageLink 不触发 UI 刷新。
| # | 方案 | 原理 | 结果 |
|---|---|---|---|
| 1 | setInterval + @State | 组件内定时器更新 | 不刷新 |
| 2 | 哑计数器 + new Date() | @State _t 每秒++,build() 里取时间 | 不刷新 |
| 3 | @Provide/@Consume | Index 定时器 → 信号广播 | 不刷新 |
| 4 | AppStorage + @StorageProp | EntryAbility 定时器 → AppStorage | 不刷新 |
| 5 | AppStorage + @StorageLink | 双向绑定替换 @StorageProp | 不刷新 |
| 6 | EntryAbility 全局定时器 | 最外层 UIAbility 推 AppStorage | 不刷新 |
所有方案共用一个死穴:时钟显示在 Tabs→TabContent 子页面内。官方示例用 @Entry + Canvas,没有 TabContent 这层。TabContent 可能做了渲染优化导致子组件 @State 变更不触发重渲染。
2 小时,9 个源文件,6 次试错。以下是每条用时间换来的铁律。
一个变量只用一个状态装饰器。显式 @Provide('key') 最稳。
ArkTS 不走 JS 的松类型,必须 interface 或 class。
直接用 height()。编译器错误提示很准,读它。
module.json5 只是备案,还得 requestPermissionsFromUser 弹窗。
@Provide/@Consume、AppStorage 全部失效。
文档有但散,API 回调容易写错,示例都是 @Entry 级别。
6 月 24 日晚,2 小时。跑通了不少,卡在了两个核心功能上。
| 功能 | 状态 | 备注 |
|---|---|---|
| 5 页 UI 骨架 | ✅ | 首页/工具/生活/智趣/我的,Tab 导航 |
| 全屏沉浸 | ✅ | setWindowLayoutFullScreen + 安全区 48px |
| emoji TabBar | ✅ | 🏠🛠🌿🎯👤,barHeight 62,选中琥珀色 |
| Toast 交互 | ✅ | 所有卡片可点,promptAction.showToast |
| 时间转换器 | ✅ | Unix↔UTC↔GPS 周/秒 |
| 定位权限 | ✅ | 声明 + runtime 弹窗 = 已授权 |
| GPS 监听注册 | ✅ | satelliteStatusChange API 正确调用 |
| UTC 实时刷新 | ❌ | 6 种方案全不行 |
| GPS 数据显示 | ❌ | 根因和 UTC 相同 |
总体完成度
65%