HarmonyOS技术精讲-Form Kit(卡片开发服务)第1篇:初识Form Kit——卡片开发的基础概念

在这里插入图片描述

开篇:为什么需要Form Kit

在HarmonyOS开发中,“卡片”是一种轻量级的UI呈现方式,用户无需打开应用,就能在桌面或负一屏看到应用的关键信息并完成简单交互。很多人在第一次接触卡片开发时,会疑惑:这到底是一个Ability还是Widget?开发时应该用ArkTS还是JS?为什么我的卡片在桌面上显示不了?

这些问题背后的核心是Form Kit(卡片开发服务)。它定义了一套完整的框架,让应用能够向系统桌面、负一屏等地方提供可动态更新的UI片段。本文先帮你建立全局认知,后续再深入实战。

它解决什么问题

卡片的本质是“应用在系统桌面上的快捷窗口”。它可以:

  • 展示实时信息(天气、日历、待办)
  • 提供快捷操作(播放控制、计时器)
  • 无需启动主Ability,降低交互成本

不适合的场景:复杂交互、长表单、视频播放。卡片推荐尺寸有限(2×2、4×4等),且生命流程与宿主Ability独立。

与传统的Widget(如Android AppWidget)相比,HarmonyOS的Form Kit在生命周期绑定更新机制多端适配上做了更细化的设计。

核心概念:提供方与使用方

角色 说明 对应组件
提供方 真正提供卡片UI和数据的应用 FormExtensionAbility + 卡片UI页面
使用方 显示卡片的系统界面 桌面、负一屏、其他支持卡片的应用

一张卡片从创建到销毁,需要经历以下流程:

  1. 用户添加卡片 → 使用方请求提供方创建卡片实例。
  2. 提供方返回卡片内容 → 通过FormExtensionAbilityonCreate回调,返回绑定数据。
  3. 使用方渲染卡片 → 基于ArkUI或JS框架渲染,并定期或按需更新。
  4. 卡片交互 → 用户点击卡片,可触发click事件跳转或更新。
  5. 卡片销毁 → 用户移除卡片时,调用onDestroy清理。

ArkTS卡片 vs JS卡片:如何选择

HarmonyOS提供两种卡片开发范式:ArkTS卡片(推荐)和 JS卡片(已逐步废弃)。

对比项 ArkTS卡片 JS卡片
语言 ArkTS(TypeScript超集) JavaScript/Ace
UI框架 ArkUI声明式 JS模板语法
特性支持 动画、自定义绘制、双向通信 仅基础组件和简单事件
更新机制 支持本地和远程更新,可控制刷新频率 受限,建议用定时更新
性能 更好,编译优化 中等
官方推荐 是(新项目必选) 否(仅维护已有项目)

实际开发建议:如果从零开始,直接选择ArkTS卡片。JS卡片的生命周期和UI更新限制较多,遇到复杂需求容易踩坑。

Form Kit框架组成

Form Kit主要由以下模块构成:

  • FormExtensionAbility:卡片提供方必须继承的Ability,用于管理卡片创建、更新、销毁。
  • FormConfig.json:配置文件,声明卡片名称、尺寸、更新周期、支持端侧等。
  • 卡片UI页面:ArkTS卡片对应一个@Entry @Component组件,JS卡片对应index.hml等文件。
  • FormManager:系统统一管理卡片实例的服务,负责分发事件、控制刷新。

最简卡片声明与配置(ArkTS)

下面不是完整项目,只展示关键代码片段。假设你的应用包名为com.example.myform

1. 配置module.json5(在对应entry的module.json5中)

{
  "abilities": [
    {
      "name": "EntryFormAbility",
      "srcEntry": "./ets/entryability/EntryFormAbility.ts",
      "formsEnabled": true,
      "forms": [
        {
          "name": "WeatherForm",
          "displayName": "$string:weather_form_name",
          "description": "天气卡片",
          "src": "./ets/forms/WeatherCard.ets",
          "window": {
            "designWidth": 100,
            "autoDesignWidth": true
          },
          "formConfigAbility": "ability://com.example.myform.EntryFormAbility",
          "updateEnabled": true,
          "scheduledUpdateTime": "10:30",
          "updateDuration": 1,
          "defaultDimension": "2*2",
          "supportDimensions": ["2*2", "4*4"]
        }
      ]
    }
  ]
}

关键字段说明

  • formsEnabled:必须设为true
  • srcEntry:FormExtensionAbility的入口文件。
  • forms数组:每张卡片一个条目。src指向卡片UI组件。
  • updateEnabledupdateDuration:控制卡片自动更新时间(分钟),最小1分钟。

2. FormExtensionAbility实现

// EntryFormAbility.ts
import { FormExtensionAbility } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';

export default class EntryFormAbility extends FormExtensionAbility {
  onCreate(want: Want) {
    // 创建卡片时回调,返回初始数据(JSON对象)
    return { temperature: '25°C', city: '上海' };
  }

  onUpdate(formId: string) {
    // 定时更新或主动调用时回调,返回新数据
    return { temperature: '26°C', city: '上海' };
  }

  onDestroy(formId: string) {
    // 卡片被移除时清理资源
    console.info(`Form ${formId} destroyed`);
  }
}

3. 卡片UI组件(ArkTS)

// WeatherCard.ets
@Entry
@Component
struct WeatherCard {
  @LocalStorageProp('temperature') temperature: string = '';
  @LocalStorageProp('city') city: string = '';

  build() {
    Column() {
      Text(this.city).fontSize(14).fontWeight(FontWeight.Bold)
      Text(this.temperature).fontSize(24).fontColor(Color.Orange)
      Button('刷新').onClick(() => {
        // 可调用updateForm接口主动刷新
      })
    }
    .width('100%').height('100%')
    .padding(10)
    .backgroundColor(Color.White)
  }
}

注意:卡片UI组件不能使用@State直接从本地更新,必须通过@LocalStorageProp从FormExtensionAbility返回的数据中读取。更新数据由系统通过onUpdateupdateForm接口推动。

常见问题:卡片生命周期与数据同步

坑1:卡片创建后UI不更新

现象:在onCreate中返回了数据,但卡片显示空白或默认值。

原因onCreate返回的数据需要与卡片的@LocalStorageProp变量名一致。系统会把数据存入LocalStorage,组件才能读取。如果组件中变量名写错,数据自然丢失。

解决方案:确保返回的JSON键名与@LocalStorageProp('key')的key完全匹配。建议在onCreate中打印日志确认数据格式。

坑2:定时更新不生效

现象:设置了updateDuration: 1(分钟),但卡片并未按1分钟刷新。

原因:系统对频繁更新有限制。updateDuration最小值为30分钟(实际值为30),如果你的值小于30,系统会忽略并采用30分钟。文档未明确说明,实测有效。

解决方案:如需更细粒度的刷新,建议使用formProvider.updateForm()主动触发,或结合定时任务。被动定时刷新只能30分钟起步。

最佳实践

  1. 尽可能减少@LocalStorageProp变量数量:每个变量都会在更新时触发整个卡片重建,变量过多会明显卡顿。推荐用单个JSON对象包裹所有数据。
  2. 避免在卡片UI中使用复杂动画:卡片布局引擎限制动画时长和类型,建议只使用基础显隐或透明度变化。
  3. 及时释放onDestroy中的资源:卡片实例数量有限,如果删除卡片后未能清理订阅或定时器,会导致内存泄漏。在onDestroy中取消所有事件监听。

FAQ

Q:为什么我的卡片在模拟器上能打开,但真机桌面没显示?
A:模拟器桌面可能不完整。真机上需要确认module.json5formsEnable为true,且卡片配置了supportDimensions。另外负一屏卡片需要额外配置formConfigAbility

Q:卡片支持点击跳转吗?
A:支持。在卡片UI中使用ButtonText绑定onClick事件,跳转其他Ability需通过common.UIAbilityContext.startAbility,但需要先获取卡片宿主Context,不能直接使用当前AbilityContext。

Q:JS卡片还能继续用吗?
A:可以,但官方不再增加新特性。API 12以后的新项目推荐全部迁移至ArkTS卡片。

示例代码地址:项目地址


以上内容基于HarmonyOS NEXT API 12及以上版本,具体行为请以真机运行结果为准。

Logo

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

更多推荐