HarmonyOS Form 卡片刷新治理:创建、更新与数据快照一致性

服务卡片看起来像一个小页面,但它的运行边界和普通页面不同。卡片创建、数据更新、定时刷新、用户点击都要通过 FormExtensionAbility 与 formProvider 协作。本文用运动路线卡片场景,把卡片数据快照、formId 管理和主动更新链路写成可维护结构。

请添加图片描述

本文先把卡片数据不同步讲清

卡片常见问题是主应用已经刷新,桌面卡片还停留在旧数据。要解决这个问题,必须把 formId、数据快照、更新时机和异常重试设计清楚。

  • onAddForm 只返回初始快照。
  • formId 要保存,便于后续主动更新。
  • 快照字段保持轻量稳定。
  • 更新失败要保留下一次重试机会。

Form 资料与声明入口

项目 内容
本地声明 D:/harmonyos/SDK/23/ets/api/@ohos.app.form.FormExtensionAbility.d.ts
更新接口 D:/harmonyos/SDK/23/ets/api/@ohos.app.form.formProvider.d.ts
关键对象 FormExtensionAbility、formProvider、formId、卡片数据对象。
边界 卡片展示数据应是轻量快照,不直接承载完整页面状态。

卡片刷新的版本边界

项目 内容
SDK HarmonyOS SDK 23。
场景 路线步数、天气、最近轨迹摘要。
数据策略 卡片读取快照,主应用负责生成快照。
边界 卡片不是后台常驻页面,不应在卡片里做重型网络逻辑。

请添加图片描述

请添加图片描述

先定义卡片快照结构

卡片需要的是可直接展示的数据,不是完整路线对象。快照字段越稳定,卡片更新越不容易被业务实体变化影响。

export interface RouteFormSnapshot {
  title: string;
  city: string;
  distanceText: string;
  updatedAtText: string;
}

export const EmptyRouteForm: RouteFormSnapshot = {
  title: '暂无路线',
  city: '未选择城市',
  distanceText: '-- km',
  updatedAtText: '等待同步'
};

快照结构是卡片和主应用之间的协议。卡片只展示这些字段,不读取复杂实体。

onAddForm 返回初始数据

卡片创建时要尽快返回可展示内容。没有业务数据时返回空态快照,而不是让卡片空白。

import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility';
import formBindingData from '@ohos.app.form.formBindingData';

export default class RouteFormAbility extends FormExtensionAbility {
  onAddForm(want: Want) {
    const snapshot = RouteFormSnapshotStore.latest() ?? EmptyRouteForm;
    return formBindingData.createFormBindingData(snapshot);
  }
}

ExtensionAbility 只提供卡片初始绑定数据。复杂计算放在 SnapshotStore,避免卡片入口变重。

保存 formId 才能主动更新

用户可能添加多个同类卡片。每个 formId 都要保存,主应用刷新路线后才能逐个更新。

export class RouteFormRegistry {
  private ids = new Set<string>();

  add(formId: string): void { this.ids.add(formId); }
  remove(formId: string): void { this.ids.delete(formId); }
  all(): string[] { return Array.from(this.ids); }
}

注册表管理卡片实例。它不关心快照内容,只解决“要更新哪些卡片”的问题。

主动更新走 formProvider

主应用生成新快照后,遍历 formId 调用 updateForm。失败时记录 formId,留到下次同步。

import formProvider from '@ohos.app.form.formProvider';

export async function updateRouteForms(registry: RouteFormRegistry, snapshot: RouteFormSnapshot): Promise<void> {
  const data = formBindingData.createFormBindingData(snapshot);
  for (const formId of registry.all()) {
    try {
      await formProvider.updateForm(formId, data);
    } catch (err) {
      console.error(`[RouteForm] update failed formId=${formId}`);
    }
  }
}

更新函数负责把业务快照推给卡片。它按 formId 单独处理异常,避免一个卡片失败影响其他卡片。

删除卡片时清理注册表

用户删除桌面卡片后,应用侧如果还保留 formId,后续更新会不断失败。

onRemoveForm(formId: string): void {
  RouteFormRegistryHolder.current().remove(formId);
  RouteFormRegistryHolder.flush();
}

删除回调只处理注册关系。清理后主动更新列表会变短,错误日志也会更干净。

定时刷新要控制数据来源

卡片刷新不适合每次都拉完整网络数据。更稳的做法是主应用维护快照,卡片刷新只读取最近可用快照。

export class RouteFormSnapshotStore {
  private static current?: RouteFormSnapshot;

  static save(snapshot: RouteFormSnapshot): void {
    this.current = snapshot;
  }

  static latest(): RouteFormSnapshot | undefined {
    return this.current;
  }
}

快照仓储降低卡片刷新成本。真实项目应把快照持久化,避免进程重启后丢失。

点击卡片只传最小参数

卡片跳转主应用时,只传 routeId 或目标页面,不传完整数据。主应用打开后再读取详情。

export const RouteFormAction = {
  TARGET_ROUTE_DETAIL: 'routeDetail',
  PARAM_ROUTE_ID: 'routeId'
} as const;

点击协议保持轻量。卡片负责唤起,主应用负责加载业务详情。

卡片验证流程:创建、刷新、删除逐个走通

Form 卡片验证至少覆盖三个动作:添加卡片时能看到初始快照,主应用更新路线后桌面卡片能刷新,删除卡片后注册表不再保留旧 formId。还要模拟其中一个 formId 更新失败,确认其他卡片仍能继续更新。这样才能证明卡片是按实例治理,而不是只在单卡片场景下正常。多实例场景尤其容易暴露问题:用户可能同时放置小尺寸路线卡片和大尺寸统计卡片,它们读取同一个快照来源,但展示字段和刷新频率不同,所以更新函数必须按 formId 独立处理结果。

async function verifyRouteFormUpdate(registry: RouteFormRegistry): Promise<void> {
  const snapshot: RouteFormSnapshot = {
    title: '周末山地路线',
    city: '杭州',
    distanceText: '12.8 km',
    updatedAtText: '刚刚更新'
  };
  await updateRouteForms(registry, snapshot);
}

验证入口构造一个轻量快照并执行主动更新。它可以配合日志确认每个 formId 的更新结果,也能验证快照字段是否足够支撑不同尺寸卡片展示。若桌面上同时存在多个卡片实例,日志中应该能看到每个 formId 的独立更新结果。

HarmonyOS Form 卡片刷新治理排查表

现象 优先查看 处理方式
桌面卡片不刷新 formId 是否保存 onAddForm 时登记,onRemoveForm 时清理。
只有部分卡片刷新 updateForm 是否逐个处理异常 单个 formId 失败不能中断全部更新。
卡片显示空白 初始快照是否为空 提供 EmptyRouteForm。
卡片刷新很慢 是否在卡片侧做重型网络逻辑 主应用生成轻量快照。

HarmonyOS Form 卡片刷新治理验收清单

上线或交付前建议逐项确认,尤其是生命周期、异常分支和数据一致性。

  • 卡片数据是轻量快照。
  • 每个 formId 都有注册和删除逻辑。
  • 主动更新使用 formProvider.updateForm。
  • 更新异常按 formId 记录。
  • 卡片点击只传最小参数。

小结

Form 卡片的稳定性来自快照一致性。主应用生成数据,卡片展示数据,formId 管理实例,formProvider 负责推送,这几层分开后刷新链路就清楚了。

参考资料

以下资料用于核对 API 名称和能力边界,落地时请结合项目目标 API 版本复核。

  • HarmonyOS SDK 23 本地 API 声明:@ohos.app.form.FormExtensionAbility.d.ts
  • HarmonyOS SDK 23 本地 API 声明:@ohos.app.form.formProvider.d.ts
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐