起因:我想把自己的精力变化「看见」

去年有段时间状态特别差,每天下午三点准时犯困,开会完脑子一片浆糊,但又说不清到底是什么在消耗我。

市面上的情绪记录App我试了好几个,要么让我写一大段日记(我懒),要么就是打个心情emoji完事(太粗糙)。我想要的是一个特别轻量的东西——就像手机电量百分比一样,随手记一笔"+20 跑步回来精神了"或者"-30 项目评审被锤了",然后在时间轴上看到今天的能量流向。

于是我做了「元気手账」。iOS 版先上了,用 SwiftData 写的,核心就四个模型:EnergyRecord(精力变化记录)、DailyBaseline(每天的基准电量)、Project(方舟项目,追踪精力投在哪)、QuickAction(快捷动作条)。跑了一段时间自己用着挺顺手,就开始琢磨鸿蒙版。

为什么要做鸿蒙版

说实话,不是因为什么"看好鸿蒙生态"这种大话。

原因很朴素:我手边有一台 Mate 60,日常双持。iOS版我自己用着爽,但换到华为手机的时候就断了,记录习惯一中断基本就废了。加上 HarmonyOS NEXT 搞纯血鸿蒙,ArkTS 开发工具链也成熟了不少,我想趁这波把坑踩一遍。

另外 CSDN 和华为开发者社区对 HarmonyOS 内容确实有流量倾斜,这个我不装,也是动力之一。

移植过程中最头疼的三件事

1. 数据层从 SwiftData 到关系型存储的思维切换

iOS 版用 SwiftData 特别舒服,@Model 一标注,关系用 @Relationship 一声明就完事了。比如 ProjectEnergyRecord 的一对多关系:

@Model
final class Project {
    var id: UUID = UUID()
        var name: String = ""
            var exp: Double = 0
                var level: Int = 1
                    var isLegendary: Bool = false
                        var totalSeconds: Int = 0
    @Relationship(deleteRule: .nullify, inverse: \EnergyRecord.project)
        var records: [EnergyRecord] = []
        }
        ```
到了鸿蒙这边,我用的是 `@ohos.data.relationalStore`,得自己建表、自己写 SQL、自己维护外键。说白了就是从 ORM 退回到手写 SQL 的年代。

一开始我想偷懒直接把数据全塞 JSON 存 preferences,后来记录一多查询就卡,老老实实换成了关系型数据库。这个弯路大概浪费了两天。

### 2. ArkUI 的状态管理和 SwiftUI 的差异

SwiftUI 里 `@State`、`@Observable`、`@Environment` 这套我很熟。ArkTS 里对应的是 `@State`、`@Prop`、`@Link`、`@Provide/@Consume`,概念上类似但细节上坑不少。

比如我做时间轴视图的时候,父组件的电量列表更新了,子组件的曲线图没刷新。排查了半天发现是 `@Prop` 传的是值拷贝而不是引用,应该用 `@Link`。这种事在 SwiftUI 里也踩过类似的坑,但鸿蒙的文档当时写得比较模糊,Stack Overflow 上相关问答也少,基本靠自己试。

### 3. 快捷动作条的交互实现

iOS 版的 QuickAction 是一个横向滚动条,点一下就记录一笔,delta 值预设好的。这个交互在 ArkUI 里用 `List` 横向布局加 `onClick` 就能实现,但我想加一个长按编辑的手势,这时候发现 ArkUI 的手势系统和 SwiftUI 差别挺大。

最后用了 `GestureGroup` 配合 `LongPressGesture` 和 `TapGesture` 的组合,调了几版才让长按和点击不冲突。

```arkts
Row() {
  ForEach(this.quickActions, (action: QuickActionItem) => {
      Column() {
            Image($r(`app.media.${action.icon}`))
                    .width(28).height(28)
                          Text(action.title)
                                  .fontSize(12)
                                      }
                                          .gesture(
                                                GestureGroup(GestureMode.Exclusive,
                                                        LongPressGesture({ repeat: false, duration: 500 })
                                                                  .onAction(() => { this.editAction(action) }),
                                                                          TapGesture({ count: 1 })
                                                                                    .onAction(() => { this.recordDelta(action.delta, action.title) })
                                                                                          )
                                                                                              )
                                                                                                })
                                                                                                }
                                                                                                .width('100%')
                                                                                                ```
这段是简化过的,实际还有动画和 haptic feedback 的处理,但核心思路就是这样。

## 几个做对了的决策

**"电量"隐喻而不是"情绪"** 这个决定是在 iOS 版就定下来的。跟朋友聊的时候发现,很多人对"记录情绪"有心理负担——觉得太私密,或者觉得矫情。但"今天还剩多少电"这个说法大家秒懂,记录起来也没压力。一个 delta 值加一句话,三秒钟搞定。

**方舟项目维度。** 这个功能是后来加的。我自己记了两周发现光看总电量曲线还不够,我想知道"到底是哪个项目把我榨干的"。加了 Project 维度之后,我真的发现写代码其实不怎么费电,反而是写文档和开需求评审会最消耗精力。这个洞察直接影响了我排日程的方式。

**纯本地存储,不联网。** 精力数据算是挺私密的东西,我不想碰云端同步这个坑(也没精力搞服务器)。iOS 版用 App Group + SwiftData 本地存储,鸿蒙版用 relationalStore 存在应用沙箱里。这个在 HarmonyOS 的隐私审核上也省了很多事。

## 当前状态和一些数据

坦白说,鸿蒙版刚上架不久,下载量还很小。七天数据基本是零,付费也是零。

这个我有心理准备。独立开发者做工具类App,冷启动就是这样。iOS 版也是上架头两周没什么动静,第三周在某个效率社区被人分享了一次才开始有自然流量。

鸿蒙的应用市场分发逻辑和 App Store 不太一样,我还在摸索。目前版本号 1.2.0,基本功能都有了:电量记录、时间轴、方舟项目、快捷动作条、周/月统计图。接下来想加的是桌面卡片(HarmonyOSFormAbility),让用户不打开App就能看到当前电量。

## 鸿蒙开发的体感

说几个真实感受:

**DevEco Studio 比两年前好用太多了。** 预览器虽然偶尔抽风,但日常开发够用。热重载的速度可以接受。

**ArkUI 的声明式写法学习曲线不高,** 特别是如果你写过 SwiftUI 或者 Flutter。但一些组件的行为细节文档写得不够清楚,经常得靠试。

**鸿蒙应用市场的审核比 App Store 快,** 基本一两天就过了。但应用市场内的搜索权重逻辑我到现在没完全搞明白。

**有点可惜的是**,鸿蒙的开发者社区讨论质量参差不齐,很多帖子还是"hello world"级别的入门教程,深度踩坑分享太少了。

## 我自己怎么用这个App

每天大概记 5-8 条。早上起来默认 50 点电量(如果昨晚睡得好会手动调到 55),然后一天下来就是加加减减。

上周有一天我发现下午两点电量已经掉到 15 了——上午连着开了三个会。看到这个数字我直接取消了下午的一个非必要会议,出去走了二十分钟。回来记了个"+15 散步",剩余电量够我把当天最重要的代码写完。

这种"量化→决策"的反馈循环,说实话是我做这个App之前没想到的。我以为记录就是记录,没想到看到数字会真的改变行为。

## 写在后面

如果你也在做 HarmonyOS 开发,或者对 ArkTS/ArkUI 有兴趣,欢迎交流。我踩过的坑不少,特别是 SwiftData 到 relationalStore 的数据层迁移、ArkUI 手势系统的组合用法这些,如果有人感兴趣我可以单独写一篇展开讲。

应用商店搜「元気手账」就能找到。
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐