鸿蒙 Next 卡片开发实战:从 0 到 1 构建运动数据桌面小组件

一个看似简单的小组件,踩了十几个坑,从进程隔离到跨 Context 通信,从 Builder 传参 Bug 到精度丢失——这篇文章带你完整走一遍鸿蒙卡片开发的真实体验。


背景

我们的 App 是一个运动健康类应用(类似 Keep),需要开发三个桌面卡片:

  • 本周跑步(2×2):显示本周 7 天柱状图 + 总距离
  • 本月跑步(2×4):显示日历热力图 + 统计数据
  • 本年跑步(4×4):显示 12 个月柱状图 + 统计数据

数据来源于服务端 API,需要实现以下刷新时机:

  • 用户登录后刷新数据
  • 上传运动数据后刷新
  • 退出登录时清空数据

听起来很简单对吧?我也这么想的。直到我打开了鸿蒙的官方文档…


架构设计:谁来做数据请求?

第一版(错误):鸿蒙端自己做 HTTP 请求

最初的想法是在鸿蒙端的 FormExtensionAbility 中直接调用 HTTP API 获取数据。

为什么错了?

我们的 Flutter 代码中已经有完整的 API 定义(Retrofit + Dio),包括 Token 管理、错误处理、数据模型。如果在鸿蒙端再写一遍:

  1. 代码重复,维护两套 API 层
  2. Token 管理复杂(鸿蒙端需要从 Flutter 传 Token)
  3. 数据模型要两边对齐

最终方案:Flutter 拉数据,MethodChannel 传数据

Flutter 调用 API → 拿到数据 → jsonEncode → MethodChannel → 鸿蒙 Plugin 接收 → 存储 → 刷新卡片

鸿蒙端只负责接收数据、存储、刷新 UI,不做任何网络请求。


第一坑:数据写入了但卡片不刷新——进程隔离的真相

这是整个开发过程中最大的坑。

问题现象

Flutter 端 API 返回数据 → MethodChannel 传到鸿蒙 → SportWidgetPlugin 收到 → 写入数据 → 但卡片显示的还是空数据。

排查过程

  1. 数据写入成功saveWidgetData 日志显示数据正常
  2. 读取为空:FormAbility 的 onUpdateForm 中读数据时,json length=0
  3. 怀疑 Preferences 不互通:Plugin 用 ApplicationContext,FormAbility 用 FormExtensionContext

查阅官方文档后找到关键信息:

卡片提供方进程:提供卡片的应用进程,包括应用自身 UIAbility 运行的主进程,以及卡片单独的 FormExtensionAbility 进程。两个进程之间内存隔离,但是共享相同的文件沙箱。

真相大白:

  • Plugin 运行在主进程
  • FormAbility 运行在独立进程
  • 两个进程的 Context 不同 → Preferences 存储路径不同 → 数据不互通
  • 静态变量也不通(不同进程内存隔离)
  • 文件沙箱共享 ← 这是突破口

解决方案:用文件存储桥接两个进程

Plugin(主进程)  →  写文件 (ApplicationContext.filesDir/szxd_widget_data_week.json)
                                               ↓ 共享文件沙箱
FormAbility(独立进程) → 读文件 (ApplicationContext.filesDir/szxd_widget_data_week.json)

核心代码:

// WidgetDataFileStore.ets - 跨进程共享的文件存储
export class WidgetDataFileStore {
   
   
  // 关键:用 getApplicationContext().filesDir,主进程和 FormAbility 进程都能访问
  private static getFilePath(context: common.Context, type: SportWidgetType): string {
   
   
    const appContext = context.getApplicationContext();
    return appContext.filesDir + '/' 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二蛋和他的大花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值