Form Kit(卡片开发服务)笔记03:卡片UI开发与数据更新
开发HarmonyOS卡片时,UI渲染与数据更新是核心需求。卡片运行时独立于应用进程,数据更新必须通过FormProvider、FormLink、LocalStorage三者协同完成。本文梳理卡片UI开发的基本模板,以及定时刷新、事件触发刷新、本地存储通信和事件回传的具体实现。


核心概念
卡片UI基于ArkUI声明式框架,使用@Component装饰器定义组件结构。卡片运行在独立进程中,数据更新无法像普通页面那样直接绑定状态变量,需要显式触发同步机制。
FormKit提供以下数据更新机制:
- 定时刷新:通过配置文件设定更新周期(最小值5分钟)
- 事件触发刷新 :通过
FormProvider.updateForm()接口主动推送数据 - 本地存储通信 :
LocalStorage实现卡片与Provider进程间数据共享 - FormLink通信:通过跨进程通道将事件回传至Provider
核心实现
卡片UI基础模板
卡片入口文件必须用@Entry和@Component修饰,常规做法是在widget/pages/目录下创建.ets文件。以下模板演示了如何展示数据并添加一个刷新按钮。
typescript
// widget/pages/WidgetIndex.ets
@Entry
@Component
struct WidgetCard {
@LocalStorageProp('data') data: string = '默认数据';
build() {
Column() {
Text(this.data)
.fontSize(16)
.fontColor('#FFFFFF')
Button('点击刷新')
.onClick(() => {
postCardAction(this, {
action: 'message',
data: { type: 'refresh' }
});
})
}
.width('100%')
.height('100%')
}
}
注意 :
@LocalStorageProp必须使用与Provider端LocalStorage中相同的key才能建立绑定。postCardAction的第一个参数是this,第二个参数是Action对象,action: 'message'表示向Provider发送自定义消息。
定时刷新配置
在module.json5的forms块中配置updateDuration,单位为分钟,最小值5分钟。如果希望更频繁更新,需要在Provider端通过事件触发刷新。
json
{
"forms": [
{
"name": "Widget",
"updateDuration": 30, // 单位分钟,最小值5
"supportDimensions": ["1*2"],
"defaultDimension": "1*2"
}
]
}
注意 :
updateDuration配置项只对@Form形式的定时刷新生效,且必须与formName一致。实际更新周期受系统调度影响,不会严格等于配置值。
事件触发刷新(Provider端)
当需要立即更新卡片数据时,调用formProvider.updateForm()方法。通常在主应用的Ability或服务中触发。
typescript
// 在Provider Ability中
import formProvider from '@ohos.app.form.formProvider';
function refreshCard(formId: string, data: Record<string, Object>) {
try {
formProvider.updateForm(formId, {
formData: data
}).then(() => {
console.info('卡片数据更新成功');
}).catch((err: BusinessError) => {
console.error('卡片数据更新失败', err);
});
} catch (err) {
console.error('更新异常', err);
}
}
注意 :
formId必须是从系统获取到的有效卡片ID,每次刷新都需要携带完整的数据对象(之前的数据不会被保留,需要完全覆盖)。
LocalStorage数据流转
Provider端调用localStorage.setItem()将数据写入本地存储,卡片端通过@LocalStorageProp或@LocalStorageLink读取。需要注意的是,LocalStorage实例需要在卡片创建时与Provider绑定。
typescript
// Provider写入
localStorage.setItem('data', JSON.stringify(newData));
// 卡片读取
@LocalStorageProp('data') data: string = '';
注意 :LocalStorage的key必须与卡片组件中
@LocalStorageProp('key')的key一致。如果数据是复杂对象,序列化时建议使用JSON格式,卡片端再反序列化。
FormLink事件闭环
卡片通过postCardAction将用户操作回传给Provider,Provider在onFormEvent中接收并处理。以下示例中,卡片点击刷新按钮后发送message事件,Provider根据接收到的type执行对应逻辑。
typescript
// 卡片端
postCardAction(this, {
action: 'message',
data: { type: 'refresh' }
});
// Provider Ability中处理事件
onFormEvent(formId: string, message: string) {
const data = JSON.parse(message);
if (data.type === 'refresh') {
// 执行数据刷新逻辑
refreshCard(formId, { data: '最新数据' });
}
}
以上涵盖了卡片UI开发与数据更新的主要环节。实际项目中,需要根据业务场景选择定时刷新或事件触发刷新,并注意LocalStorage和FormLink的配合使用。如果对Form Kit的其他机制有疑问,欢迎在评论区交流。
Provider写入与卡片读取的数据同步,是卡片开发中的常见问题。下面给出正确的数据读写实现方式,以及卡片事件闭环的处理方法。
typescript
// Provider写入
localStorage.setItem('data', JSON.stringify(newData));
// 卡片读取
@LocalStorageProp('data') data: string = '';
LocalStorageProp仅用于卡片侧读取已推送的数据,Provider端修改LocalStorage后必须通过formProvider.updateForm触发UI更新。直接修改LocalStorage不会反映到卡片上。
FormLink事件闭环
卡片通过postCardAction将操作回传Provider,参数action固定为'message':
typescript
postCardAction(this, {
action: 'message',
data: { actionType: 'click', value: 'xxx' }
});
Provider在onFormEvent回调中解析data字段,根据actionType进行业务处理:
typescript
onFormEvent(formId: string, message: Record<string, Object>) {
if (message.actionType === 'click') {
// 处理点击事件
}
}
注意:postCardAction中的action如果误设为'router'会导致无响应,排查时可先打印message参数确认通信是否正常。
注意事项
updateDuration取值范围5-180分钟,超出范围自动截断- 卡片数据更新频率受系统功耗管控,频繁更新可能被静默降频
@LocalStorageProp不能与@State混用- 卡片进程独立,不可直接调用页面级布局方法
常见问题 FAQ
Q:卡片配置了定时刷新但未触发?
A:检查module.json5中updateDuration是否大于等于5,且卡片处于可见状态
Q:postCardAction调用无反应?
A:确认卡片与Provider进程通信正常,action参数使用message而非router
Q:LocalStorage数据不同步?
A:Provider端必须通过formProvider.updateForm推送数据,直接修改LocalStorage不会触发UI更新
上一篇介绍了卡片基础配置与创建流程,下一篇将讲解卡片生命周期回调与状态管理。关于卡片数据同步与事件闭环的实现,欢迎在评论区提问交流。