《卡片添加至桌面》四、@ohos.app.form.FormExtensionAbility指南
HarmonyOS FormExtensionAbility(卡片扩展能力)使用指南
摘要:本文详细介绍 HarmonyOS
FormExtensionAbility的概念、生命周期、核心回调方法,以及如何通过该扩展能力实现桌面卡片的创建、更新和销毁管理。配合完整代码示例,帮助开发者快速上手应用卡片开发。
效果
一、概念概述
FormExtensionAbility 是 HarmonyOS 应用卡片的核心扩展能力,属于 @kit.FormKit。它作为卡片的服务端运行环境,负责管理卡片的完整生命周期,包括创建、更新、销毁等操作。
1.1 架构定位
┌─────────────────────────────────────────────┐
│ 桌面(Launcher) │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 卡片 UI │ │ 卡片 UI │ │
│ │ (Widget) │ │ (Widget) │ │
│ └──────┬──────┘ └──────┬──────┘ │
└─────────┼────────────────┼──────────────────┘
│ formBindingData │
┌─────────┼────────────────┼──────────────────┐
│ ▼ ▼ │
│ FormExtensionAbility(卡片服务端) │
│ ├── onAddForm() → 卡片创建 │
│ ├── onUpdateForm() → 卡片更新 │
│ ├── onCastToNormalForm() → 临时转常态 │
│ ├── onRemoveForm() → 卡片销毁 │
│ └── onAcquireFormState() → 查询状态 │
└─────────────────────────────────────────────┘
1.2 模块归属
| 属性 | 值 |
|---|---|
| 模块名 | @ohos.app.form.FormExtensionAbility |
| Kit | @kit.FormKit |
| 引入方式 | import { FormExtensionAbility } from '@kit.FormKit' |
二、生命周期与回调方法
2.1 生命周期流程
用户添加卡片
↓
onAddForm(want) ← 创建卡片,返回初始数据
↓
卡片在桌面显示
↓
onUpdateForm(formId) ← 定时更新 / 手动触发
↓
onCastToNormalForm(formId) ← 临时卡片转正
↓
用户移除卡片
↓
onRemoveForm(formId) ← 清理资源
2.2 核心回调方法
| 方法 | 触发时机 | 返回值 |
|---|---|---|
onAddForm(want) |
用户添加卡片时 | FormBindingData |
onUpdateForm(formId) |
定时更新或主动更新时 | void |
onCastToNormalForm(formId) |
临时卡片转为常态卡片时 | void |
onRemoveForm(formId) |
用户移除卡片时 | void |
onFormEvent(formId, message) |
卡片触发消息事件时 | void |
onAcquireFormState(want) |
查询卡片状态时 | FormState |
三、项目配置
3.1 创建 FormExtensionAbility
在 entry/src/main/ets/entryformability/ 目录下创建 EntryFormAbility.ets:
import { formBindingData, FormExtensionAbility, formInfo } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
export default class EntryFormAbility extends FormExtensionAbility {
onAddForm(want: Want): formBindingData.FormBindingData {
console.info('onAddForm called');
// 从 want 中获取卡片信息
let formId = want.parameters?.['ohos.extra.param.key.form_identity'] as string;
let formName = want.parameters?.['ohos.extra.param.key.form_name'] as string;
let formDimension = want.parameters?.['ohos.extra.param.key.form_dimension'] as string;
console.info(`formId: ${formId}, formName: ${formName}, dimension: ${formDimension}`);
// 构造卡片初始数据
let formData = {
formId: formId,
title: '我的卡片',
content: '欢迎使用应用卡片'
};
return formBindingData.createFormBindingData(formData);
}
onUpdateForm(formId: string): void {
console.info(`onUpdateForm: ${formId}`);
// 可在此处获取最新数据并更新卡片
}
onCastToNormalForm(formId: string): void {
console.info(`onCastToNormalForm: ${formId}`);
}
async onRemoveForm(formId: string): Promise<void> {
console.info(`onRemoveForm: ${formId}`);
// 清理该卡片相关的资源
}
onFormEvent(formId: string, message: string): void {
console.info(`onFormEvent: ${formId}, message: ${message}`);
}
onAcquireFormState(want: Want): formInfo.FormState {
return formInfo.FormState.READY;
}
}
3.2 配置 module.json5
在 module.json5 的 extensionAbilities 中注册 FormExtensionAbility:
{
"module": {
"extensionAbilities": [
{
"name": "EntryFormAbility",
"srcEntry": "./ets/entryformability/EntryFormAbility.ets",
"label": "$string:EntryFormAbility_label",
"description": "$string:EntryFormAbility_desc",
"type": "form",
"metadata": [
{
"name": "ohos.extension.form",
"resource": "$profile:form_config"
}
]
}
]
}
}
3.3 配置 form_config.json
在 entry/src/main/resources/base/profile/form_config.json 中定义卡片:
{
"forms": [
{
"name": "MyWidget",
"displayName": "$string:MyWidget_display_name",
"description": "$string:MyWidget_desc",
"src": "./ets/widget/MyWidgetCard.ets",
"uiSyntax": "arkts",
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"colorMode": "auto",
"isDynamic": true,
"isDefault": true,
"updateEnabled": false,
"scheduledUpdateTime": "10:30",
"updateDuration": 1,
"defaultDimension": "2*2",
"supportDimensions": ["2*2"]
}
]
}
3.4 关键配置项说明
| 配置项 | 说明 |
|---|---|
name |
卡片唯一标识名,对应 @Entry 组件名 |
src |
卡片 UI 组件的文件路径 |
isDynamic |
是否为动态卡片(支持实时更新) |
updateEnabled |
是否启用定时更新 |
scheduledUpdateTime |
定时更新时间(HH:mm 格式) |
defaultDimension |
默认尺寸(2*2、2*4、4*4) |
supportDimensions |
支持的尺寸列表 |
四、卡片 UI 组件开发
4.1 基础卡片组件
在 entry/src/main/ets/widget/MyWidgetCard.ets 中创建:
let localStorage = new LocalStorage();
@Entry(localStorage)
@Component
struct MyWidgetCard {
@LocalStorageProp('formId') formId: string = '';
@LocalStorageProp('title') title: string = '';
@LocalStorageProp('content') content: string = '';
build() {
Column({ space: 12 }) {
Text(this.title)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
Text(this.content)
.fontSize(14)
.fontColor('#666666')
.maxLines(3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(16)
}
}
4.2 卡片组件要点
| 要点 | 说明 |
|---|---|
必须使用 @Entry(localStorage) |
卡片入口需要绑定 LocalStorage |
数据通过 @LocalStorageProp 获取 |
数据由 FormBindingData 注入到 LocalStorage |
| 卡片不支持网络请求 | 数据需要从服务端通过 Preferences 传递 |
| 支持有限的事件 | 仅支持 postCardAction 的 router、call、message 事件 |
4.3 注册到 main_pages.json
{
"src": [
"pages/Index",
"widget/MyWidgetCard"
]
}
五、onAddForm 详解:根据卡片名称返回不同数据
当一个应用有多个卡片时,可以在 onAddForm 中根据 formName 返回不同的初始数据:
onAddForm(want: Want): formBindingData.FormBindingData {
let formId = want.parameters?.['ohos.extra.param.key.form_identity'] as string;
let formName = want.parameters?.['ohos.extra.param.key.form_name'] as string;
if (formName === 'BatteryWidget') {
// 电量卡片数据
let data = {
formId: formId,
batteryLevel: 85,
chargingStatus: '充电中'
};
return formBindingData.createFormBindingData(data);
}
if (formName === 'StorageWidget') {
// 存储卡片数据
let data = {
formId: formId,
usedGB: 64.5,
totalGB: 256.0,
usedPercent: 25
};
return formBindingData.createFormBindingData(data);
}
if (formName === 'DeviceInfoWidget') {
// 设备信息卡片数据
let data = {
formId: formId,
deviceName: 'Mate 60 Pro',
brand: 'HUAWEI',
batteryLevel: 85,
usedGB: 64.5,
totalGB: 256.0
};
return formBindingData.createFormBindingData(data);
}
return formBindingData.createFormBindingData('');
}
六、onRemoveForm 详解:清理卡片资源
当用户从桌面移除卡片时,onRemoveForm 被调用。开发者需要在此方法中清理相关资源:
import { preferences } from '@kit.ArkData';
async onRemoveForm(formId: string): Promise<void> {
console.info(`卡片被移除: ${formId}`);
// 从 Preferences 中移除该卡片的 formId 记录
let prefs = preferences.getPreferencesSync(this.context, { name: 'myStore' });
let formIdList = prefs.getSync('formIdList', []) as string[];
let index = formIdList.indexOf(formId);
if (index !== -1) {
formIdList.splice(index, 1);
prefs.putSync('formIdList', formIdList);
prefs.flush();
}
}
七、onAcquireFormState 详解:卡片状态查询
onAcquireFormState 用于返回卡片的当前状态:
onAcquireFormState(want: Want): formInfo.FormState {
// FormState 枚举:
// UNKNOWN - 未知状态
// READY - 卡片就绪
// TEMP - 临时卡片(无数据)
return formInfo.FormState.READY;
}
| 状态值 | 说明 |
|---|---|
UNKNOWN |
未知状态 |
READY |
卡片就绪,可以展示数据 |
TEMP |
临时卡片,暂无数据 |
八、常见问题与注意事项
8.1 FormExtensionAbility 运行在哪个进程?
FormExtensionAbility 运行在应用的主进程中,与 UIAbility 共享进程。但卡片 UI(Widget)渲染在桌面进程中。
8.2 onAddForm 中可以访问网络吗?
不建议在 onAddForm 中进行耗时操作(如网络请求),因为它需要快速返回 FormBindingData。建议从 Preferences 读取已缓存的数据。
8.3 如何区分多个卡片?
通过 want.parameters['ohos.extra.param.key.form_name'] 获取卡片名称来区分不同卡片,返回对应数据。
8.4 isDynamic 和 updateEnabled 的区别?
| 配置项 | 说明 |
|---|---|
isDynamic |
卡片是否支持实时更新(通过 formProvider.updateForm) |
updateEnabled |
是否启用系统定时自动更新(onUpdateForm 被周期调用) |
九、总结
| 知识点 | 内容 |
|---|---|
| 核心类 | FormExtensionAbility(继承自 ExtensionAbility) |
| Kit | @kit.FormKit |
| 创建卡片 | onAddForm(want) 返回 FormBindingData |
| 更新卡片 | onUpdateForm(formId) |
| 销毁卡片 | onRemoveForm(formId) |
| 数据传递 | formBindingData.createFormBindingData(data) |
| 配置文件 | module.json5 + form_config.json + main_pages.json |
FormExtensionAbility 是 HarmonyOS 应用卡片开发的核心基础设施,掌握其生命周期和回调方法,是实现动态卡片数据交互的关键。
更多推荐


所有评论(0)