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 卡片尺寸,支持 1x22x22x44x4
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 负责响应卡片上的用户交互事件。

卡片数据刷新策略

服务卡片的数据更新支持两种策略:

定时刷新:通过 updateEnabledscheduledUpdateTimeupdateDuration 配置,系统会在指定时间或间隔自动拉起 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);
  }
}

卡片生命周期流程

卡片UI FormExtensionAbility 桌面系统 用户 卡片UI FormExtensionAbility 桌面系统 用户 定时刷新触发 用户交互 移除卡片 长按桌面选择添加卡片 创建 FormExtension 实例 onAddForm(want) 初始化数据 返回 FormBindingData 渲染卡片 UI 显示卡片内容 onUpdateForm(formId) 获取最新数据 更新 FormBindingData 刷新 UI 展示 点击卡片按钮 onFormEvent(formId, message) 处理交互事件 移除桌面卡片 onRemoveForm(formId) 清理资源

卡片的运行限制

服务卡片运行在受限环境中,以保证系统性能和功耗:

资源限制:卡片进程的内存上限较低(约 20MB),不应在卡片中执行大量数据计算或加载大图片。建议采用"数据在应用中预处理,卡片仅做展示"的设计模式。

API 限制:卡片中无法使用全部 Ace 组件和 API。受限能力包括:不支持网络请求(需通过 FormExtensionAbility 代理)、不支持本地存储读写(需通过应用主进程提供数据)、不支持弹窗和 Toast、不支持 setInterval 等高频率定时器、不支持 Canvas 完整绘图能力(仅支持基础图形)。

生命周期限制:卡片长时间不可见时,系统可能回收卡片资源;应用进程被杀死后,卡片仍能显示最后更新的快照数据,但交互事件无法响应。

最佳实践

  1. 按需选择刷新策略:每日一次的数据(如日账单概览)用定时刷新;用户操作后立即更新的场景用主动推送。
  2. 控制卡片复杂度:2x2 卡片聚焦 1-2 个核心数值,4x4 卡片增加图表和分类,避免过度拥挤。
  3. 善用 onFormEvent:通过 message 参数实现卡片"轻交互",如点击"刷新"图标更新数据、点击"详情"跳转应用内页面。
  4. 兜底数据设计:卡片应设计无数据时的默认占位 UI,避免首次添加时显示空白。
  5. 资源按需释放:在 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' };
  }
}

推荐参考文档

Logo

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

更多推荐