042-Form Kit服务卡片
042 — Form Kit 服务卡片:从 2x2 到 4x4 的桌面数据展示实践
简介
服务卡片是鸿蒙系统的标志性能力之一,它让用户无需打开应用就能在桌面上快速查看关键信息。MoneyTrack 利用 Form Kit 实现了两种尺寸的桌面卡片:2x2 的迷你卡片(MiniCard)展示当日收支概览,4x4 的中间卡片(MiddleCard)展示月度趋势图表。通过 FormExtensionAbility 生命周期管理、form_config.json 配置和定时刷新机制,用户可以在桌面上实时掌握自己的财务状况。
form_config.json 完整配置
卡片的元信息在 form_config.json 中声明,开发者在 module.json5 中通过 formConfigPath 字段引用该文件。以下为完整配置项说明:
| 配置项 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
string | 是 | 卡片名称,在同一应用中唯一 |
dimension |
string | 是 | 卡片尺寸,支持 1x2、2x2、2x4、4x4 |
description |
string | 否 | 卡片描述,用于系统界面展示 |
updateEnabled |
boolean | 否 | 是否启用定时刷新,默认 false |
scheduledUpdateTime |
string | 否 | 定时刷新时间,格式 HH:mm,需配合 updateEnabled |
updateDuration |
number | 否 | 刷新间隔(单位:分钟),最小 30 分钟 |
formConfigAbility |
string | 否 | 卡片配置页的 ability 名称 |
landscapeLayout |
string | 否 | 横屏布局文件的模块名 |
isContainer |
boolean | 否 | 是否为容器卡片,默认 false |
multiUserEnabled |
boolean | 否 | 是否支持多用户场景,默认 false |
{
"forms": [
{
"name": "mini_card",
"dimension": "2x2",
"description": "当日收支概览",
"updateEnabled": true,
"scheduledUpdateTime": "10:00",
"updateDuration": 60,
"formConfigAbility": "FormConfigAbility"
},
{
"name": "middle_card",
"dimension": "4x4",
"description": "月度收支趋势",
"updateEnabled": true,
"scheduledUpdateTime": "08:00",
"landscapeLayout": "MiddleCardLandscape"
}
]
}
FormExtensionAbility 完整生命周期
FormExtensionAbility 是卡片的后端逻辑载体,管理卡片的完整生命周期。开发时需要继承该类并重写对应方法:
import { FormExtensionAbility, formBindingData } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
export default class MiniCard extends FormExtensionAbility {
// 用户将卡片添加到桌面时触发
onAddForm(want: Want): formBindingData.FormBindingData {
const todayData = this.getTodaySummary();
return formBindingData.createFormBindingData(todayData);
}
// 定时更新或系统触发更新时调用
onUpdateForm(formId: string) {
const newData = this.getTodaySummary();
this.updateForm(formId, formBindingData.createFormBindingData(newData));
}
// 用户从桌面移除卡片时触发,用于清理资源
onRemoveForm(formId: string) {
console.info(`Form ${formId} removed, cleaning up resources.`);
this.releaseDataConnection(formId);
}
// 用户点击卡片上的交互组件(如按钮)时触发
onFormEvent(formId: string, message: string) {
if (message === 'refresh') {
this.onUpdateForm(formId);
} else if (message.startsWith('navigate:')) {
const page = message.split(':')[1];
this.navigateToPage(page);
}
}
}
四个生命周期方法的职责明确:onAddForm 负责初始化数据绑定;onUpdateForm 负责数据刷新;onRemoveForm 负责资源释放;onFormEvent 负责响应卡片上的用户交互事件。
卡片数据刷新策略
服务卡片的数据更新支持两种策略:
定时刷新:通过 updateEnabled 和 scheduledUpdateTime 或 updateDuration 配置,系统会在指定时间或间隔自动拉起 FormExtensionAbility 执行 onUpdateForm。此方式实现简单,但刷新频率受系统限制(最小间隔 30 分钟),且用户不可见时可能被系统延迟触发。
主动推送:应用在业务逻辑中通过 formProvider.updateForm(formId, formBindingData) 主动推送数据到已添加的卡片。此方式实时性高,适合数据变化时需要立即更新的场景(如记账后刷新卡片)。使用前需先通过 formProvider.getFormsInfo() 查询当前已添加的卡片列表。
import { formProvider, formBindingData } from '@kit.FormKit';
// 记账完成后主动刷新所有卡片
async function refreshAllForms() {
const forms = await formProvider.getFormsInfo();
for (const form of forms) {
const data = formBindingData.createFormBindingData({
todayIncome: getTodayIncome(),
todayExpense: getTodayExpense()
});
await formProvider.updateForm(form.formId, data);
}
}
卡片生命周期流程
卡片的运行限制
服务卡片运行在受限环境中,以保证系统性能和功耗:
资源限制:卡片进程的内存上限较低(约 20MB),不应在卡片中执行大量数据计算或加载大图片。建议采用"数据在应用中预处理,卡片仅做展示"的设计模式。
API 限制:卡片中无法使用全部 Ace 组件和 API。受限能力包括:不支持网络请求(需通过 FormExtensionAbility 代理)、不支持本地存储读写(需通过应用主进程提供数据)、不支持弹窗和 Toast、不支持 setInterval 等高频率定时器、不支持 Canvas 完整绘图能力(仅支持基础图形)。
生命周期限制:卡片长时间不可见时,系统可能回收卡片资源;应用进程被杀死后,卡片仍能显示最后更新的快照数据,但交互事件无法响应。
最佳实践
- 按需选择刷新策略:每日一次的数据(如日账单概览)用定时刷新;用户操作后立即更新的场景用主动推送。
- 控制卡片复杂度:2x2 卡片聚焦 1-2 个核心数值,4x4 卡片增加图表和分类,避免过度拥挤。
- 善用 onFormEvent:通过 message 参数实现卡片"轻交互",如点击"刷新"图标更新数据、点击"详情"跳转应用内页面。
- 兜底数据设计:卡片应设计无数据时的默认占位 UI,避免首次添加时显示空白。
- 资源按需释放:在 onRemoveForm 中及时取消网络监听、断开数据库连接,避免内存泄漏。
项目代码案例
文件路径:entry/src/main/ets/FormAbility/MiniCard.ets(2x2 卡片)
import { FormExtensionAbility, formBindingData, formProvider } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
export default class MiniCard extends FormExtensionAbility {
onAddForm(want: Want) {
const todayData = this.getTodaySummary();
return formBindingData.createFormBindingData(todayData);
}
onUpdateForm(formId: string) {
const newData = this.getTodaySummary();
this.updateForm(formId, formBindingData.createFormBindingData(newData));
}
onRemoveForm(formId: string) {
console.info(`MiniCard ${formId} removed.`);
}
onFormEvent(formId: string, message: string) {
if (message === 'action_refresh') {
this.onUpdateForm(formId);
}
}
private getTodaySummary() {
return { todayIncome: '¥1,200', todayExpense: '¥356' };
}
}
推荐参考文档
- Form Kit 服务卡片指南
- form_config.json 配置参考
- 卡片开发最佳实践
更多推荐



所有评论(0)