卡片就是不动,先分清updateForm和onUpdateForm谁在干活
元服务卡片开发,最让人血压升高的场景之一是:主应用里数据明明更新了,updateForm 也调了,日志显示推送成功,卡片就是显示旧数据。你开始怀疑卡片是不是没刷新,手动杀进程、重新添加卡片,偶尔能好一次,下次又不行。先别急着杀进程,把 updateForm 和 onUpdateForm 的关系理清楚,能省掉一半折腾。
formProvider.updateForm() 是主动推送数据,你调用它,把 formId 和 FormBindingData 推给卡片渲染服务,卡片 UI 收到数据后刷新。它不会因此触发卡片提供方的 onUpdateForm() 生命周期回调。onUpdateForm() 是系统在定时刷新、定点刷新或使用方请求更新时敲你的门,让你提供新数据。这两件事是分开的:一个是“我推”,一个是“系统来拿”。很多人把“调了 updateForm”当成“onUpdateForm 应该被调”,方向一开始就错了。
updateForm是主动推送,onUpdateForm是系统敲门
先看主动推送的最小链路。主应用拿到 formId,构造和卡片 UI 约定好的数据键名,调用 updateForm:
typescript
import { formBindingData, formProvider } from '@kit.FormKit'
async function pushCardTitle(formId: string, title: string): Promise<void> {
const data = formBindingData.createFormBindingData({
title: title
})
try {
await formProvider.updateForm(formId, data)
console.info('卡片推送成功')
} catch (err) {
console.error(`卡片推送失败: ${JSON.stringify(err)}`)
}
}
formBindingData.createFormBindingData({ title }) 里的 title 是键名,必须和卡片 UI 侧接收的键名一致。await formProvider.updateForm(formId, data) 是异步调用,失败时会抛错误码,别只写一个 try 不打印 err。执行结果是卡片上绑定 title 的文本变成传入值。常见错误是 formId 用了旧的或者空的,以及推送数据的键名和卡片侧 @LocalStorageProp 的键名对不上——日志说“推送成功”,但卡片那边没人接。
卡片 UI 侧用 @LocalStorageProp('title') 接收,注意 V1 卡片的入口需要 @Entry(storage),只写 @State 不会自动接收推送数据。V2 卡片则按变量名接收,迁移时别把 V1 的 @LocalStorageProp 和 V2 的接收方式混着用。
卡片和提供方不在一个进程里
另一个高频误解是“主应用里改个全局变量,卡片应该能看到”。看不到。FormExtensionAbility 运行在卡片提供方进程,卡片 UI 运行在卡片渲染服务进程,两者内存隔离,@Prop、@Link、AppStorage 都跨不了进程。主应用和卡片之间要同步数据,只能走持久化加显式推送:业务数据和 formId 落盘,主应用改完数据后调用 updateForm 推给对应卡片;onUpdateForm 回调里则读取最新持久化数据再推送。不要指望单例或者全局变量替你传数据。
onAddForm 也有一个初始化要求:要返回 FormBindingData。可以先返回一个空对象,等数据拿到后再调 updateForm,这不是触发 onUpdateForm 的开关,但它是卡片初始化的必要动作。
定时刷新先看配置再怀疑人生
如果主动推送没问题,但定时刷新死活不触发,先翻 form_config.json:updateEnabled 是不是 true,updateDuration 配了多少。updateDuration: 1 通常表示 30 分钟,不是 1 分钟;首次刷新还可能在这个基础上再有偏差,卡片不可见时布局刷新也会延后。还有一个 API 26 前后的差异要注意:dataProxyEnabled 开启代理刷新后,在 API 26 之前,定时刷新和下次刷新可能不生效。升级 HarmonyOS 7、把 targetSdkVersion 提到 26 之后,这些行为变更会按新规则走,旧配置不一定还能照常工作。
排查顺序建议是:先主动推一次固定文本,验证 formId → 数据绑定 → 页面显示 这条链路通不通;链路通了再查定时回调和配置;不要一上来就杀进程。杀进程能“好一次”,恰恰说明问题在数据推送或绑定,不在进程生命周期。
更多推荐

所有评论(0)