这个 App 要解决什么问题

上个月出差跑了三个城市,回来翻手机相册想回忆去过哪些地方,发现照片里全是会议室和酒店大堂。那些走过的街道、路过的江边、绕远路发现的小巷子,什么都没留下。

运动类 App 倒是能记录轨迹,但每次都要手动开始、手动结束,忘按一次就白走了。我的需求其实很简单:不需要配速、不需要心率、不需要任何运动数据,就是想把去过的地方安静地留在地图上。翻遍应用市场没找到满意的,干脆自己写了一个——雁过留痕。一个纯粹的足迹地图 App,只干"留痕"这一件事。

最早在 iOS 上用 SwiftUI 写了第一版,今年做了 HarmonyOS 原生版本。这篇文章聊聊鸿蒙版的技术选型、核心实现,以及从 iOS 迁移到 ArkTS 的真实体感。

为什么选 HarmonyOS 原生而不是跨平台

决定做鸿蒙版的时候,一开始考虑过跨平台方案,但试了几天 ArkTS 之后改了主意。说实话,ArkUI 的声明式语法和 SwiftUI 在思路上非常接近,迁移的心智成本比我预想的低不少。

更关键的是,鸿蒙有些系统级能力确实是 iOS 生态里拿不到的。

后台持续定位的处理方式不同。 做轨迹采集类应用,后台定位是命根子。iOS 的后台定位权限审核越来越严,而 HarmonyOS 的 continuous task(长时任务)机制让后台轨迹采集有了更清晰的系统级支持。用户授权一次,App 在后台安静记录,不需要反复弹窗确认。对于"雁过留痕"这种需要全天候静默采集的场景,这个差异非常实际。

原子化服务卡片做每日足迹预览。 这个是鸿蒙独有的体验。用户不用打开 App,桌面卡片上就能看到今天走过的轨迹缩略图。我觉得这比 iOS 的 Widget 更适合做这种"瞄一眼就够"的信息展示,因为卡片本身可以承载更丰富的交互。

核心技术实现

轨迹采集与地图渲染

轨迹记录的核心逻辑不复杂,但细节很多——GPS 漂移过滤、低速状态下的降频采集、电量优化策略,每一项都能单独写一篇。地图渲染这块用了 HarmonyOS 的 MapComponent,把采集到的坐标点用 Polyline 画到地图上。骨架代码长这样:

@Entry
@Component
struct TrackMapView {
  @State pathPoints: Array<mapCommon.LatLng> = []
  build() {
      Column() {
            MapComponent({
                    mapOptions: { center: { latitude: 39.9, longitude: 116.4 }, zoom: 12 }
                          })
                                  .onReady((map) => {
                                            let polylineOpt: mapCommon.MapPolylineOptions = {
                                                        points: this.pathPoints,
                                                                    clickable: false,
                                                                                width: 8,
                                                                                            color: 0xFF3A7DFF
                                                                                                      }
                                                                                                                map.addPolyline(polylineOpt)
                                                                                                                        })
                                                                                                                                .width('100%')
                                                                                                                                        .height('80%')
                                                                                                                                            }
                                                                                                                                              }
                                                                                                                                              }
                                                                                                                                              ```
做的事情很直白:把坐标数组丢给地图组件,画一条线。实际项目里还有轨迹平滑、分段着色之类的处理,但骨架就是这个样子。如果你做过类似的地图应用,应该对这个模式很熟悉。

### 原子化服务卡片

桌面卡片是我觉得鸿蒙版比 iOS 版体验提升最明显的地方。每天凌晨自动截取前一天的轨迹缩略图,更新到卡片上。用户早上解锁手机,一眼就看到昨天的足迹轮廓。

```arkts
@Entry
@Component
struct TrackWidgetCard {
  @LocalStorageProp('todayDistance') todayDistance: string = '0 km'
    @LocalStorageProp('trackSnapshot') trackImg: string = ''
  build() {
      Column({ space: 8 }) {
            Text('昨日足迹')
                    .fontSize(14)
                            .fontColor('#666')
                                  Image(this.trackImg)
                                          .width('100%')
                                                  .aspectRatio(1.6)
                                                          .borderRadius(8)
                                                                Text(this.todayDistance)
                                                                        .fontSize(20)
                                                                                .fontWeight(FontWeight.Medium)
                                                                                    }
                                                                                        .padding(12)
                                                                                          }
                                                                                          }
                                                                                          ```
卡片上只放两样东西:一张轨迹缩略图和一个距离数字。克制一点,信息密度刚刚好。

## 从 SwiftUI 到 ArkTS 的迁移体感

这部分可能对同样在考虑双端开发的同学有参考价值,我尽量说具体。

**布局系统上手快。** ArkUI 的 Column、Row、Stack 和 SwiftUI 的 VStack、HStack、ZStack 几乎是一一对应的。我把 iOS 端的 UI 结构搬过来,改改语法,大部分页面半天就能跑起来。有 SwiftUI 经验的开发者在这一步几乎没有学习成本。

**状态管理思路有差异。** SwiftUI 用 @State、@ObservedObject 那套,ArkTS 的 @State、@Link、@Prop 的作用域划分更细。刚开始会有点不习惯,但写了两三个页面之后反而觉得鸿蒙这套更明确——谁持有数据、谁只是引用,代码里看得更清楚。

**工具链成熟度还在追赶。** DevEco Studio 用下来整体还行,但和 Xcode 比的话,断点调试、性能分析这些工具还有打磨空间。不过每个版本都能感觉到在进步,这个倒不是什么阻塞性问题。

**设备适配是加分项。** 同一套代码跑在手机、平板、折叠屏上,ArkUI 的自适应布局能力确实省了不少事。雁过留痕在 MatePad 上展开地图的效果比手机上好太多,大屏看轨迹图那种满足感是小屏给不了的。

## 关于产品定位的克制

开发过程中最难的部分不是技术,是忍住不加功能。总有人建议加社交分享、加运动数据统计、加打卡排行榜。但我一直觉得,这个 App 的价值恰恰在于它什么都不多做。你出门,它安静记录;你想看了,打开地图,所有去过的地方一目了然。没有点赞,没有评论,没有"今日步数打败了 98% 的用户"。

有次出差结束看了一眼全年轨迹图,发现自己居然去过三十多个城市。地图上那条慢慢延伸的线,就是你存在过的证据。雁过留痕,名字里说的就是这么回事。

## 后续计划

鸿蒙版目前在持续迭代中,后面打算尝试跨设备流转——手机上录的轨迹,在平板上查看大地图,在手表上快速看今日路线。这些场景在 HarmonyOS 的分布式架构下实现起来会比较自然,也是我选择原生开发而不是跨平台的重要原因。

如果你也在做鸿蒙开发,特别是后台定位功耗优化和地图渲染性能这两块踩过坑的,欢迎留言交流。独立开发者的路上,互相聊聊技术方案比闷头写代码效率高多了。

#HarmonyOS开发 #ArkTS #ArkUI #原子化服务 #鸿蒙原生应用
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐