HarmonyOS技术精讲-Form Kit(卡片开发服务)第3篇:深入卡片配置与生命周期管理
HarmonyOS技术精讲-Form Kit(卡片开发服务)第3篇:深入卡片配置与生命周期管理

卡片配置与生命周期,到底难在哪
HarmonyOS NEXT 的卡片开发里,form_config.json 的配置和生命周期回调的配合,是初学者最容易踩坑的地方。很多人按照官方示例配置了 updateDuration,结果卡片根本不按预期刷新;或者在 onDestroy 里没做资源清理,导致应用退出后还有残留进程。
这篇文章不绕弯子,直接聚焦两个核心问题:
form_config.json里每个配置项到底控制什么,哪些是关键敏感项- 生命周期回调的触发顺序和参数含义,以及 Provider 和 Manager 如何协作
它解决什么问题
卡片开发分为配置层和运行层。配置层决定卡片长什么样、什么时候更新、支持哪些尺寸;运行层决定卡片在用户桌面上的实际行为,比如点击响应、数据刷新、销毁清理。
这两个层面必须对齐,否则就会出现“配置了定时更新但没效果”、“切换尺寸后 UI 错乱”这类问题。
| 维度 | 配置层 (form_config.json) | 运行层 (Provider) |
|---|---|---|
| 职责 | 声明卡片外观、更新策略、尺寸 | 处理生命周期事件、返回数据 |
| 关键文件 | form_config.json + 资源文件 |
FormExtension 子类 |
| 输出 | 元数据 | FormBindingData 对象 |
环境说明
DevEco Studio 版本:DevEco Studio 6.1.0 及以上
HarmonyOS SDK 版本:HarmonyOS 6.1.0(23) 及以上
目标设备:手机 / 平板
开发语言:ArkTS
核心实现:配置多样式尺寸与定时更新
下面通过一个完整示例,演示如何配置三种尺寸的卡片,并实现定时刷新。
1. form_config.json 配置
这段配置声明了卡片支持 1x2、2x2、2x4 三种尺寸,默认 2x2,每 30 分钟自动更新一次。
{
"forms": [
{
"name": "MultiSizeWidget",
"displayName": "多功能卡片",
"description": "支持多种尺寸和定时更新",
"src": "./ets/forms/WidgetFormProvider.ets",
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"colorMode": "auto",
"isDefault": true,
"updateEnabled": true,
"updateDuration": 30,
"defaultDimension": "2*2",
"supportDimensions": ["1*2", "2*2", "2*4"],
"formConfigurable": true,
"transparencyEnabled": false
}
]
}
这里重点说明几个容易忽略的配置项:
updateDuration:单位是分钟,最小值为 30。小于 30 会被静默调整为 30,很多人配置 1 或 5 发现不生效就是这个原因。formConfigurable:设为 true 时,用户长按卡片可以进入配置页面;设为 false 则直接添加到桌面。这个开关影响用户交互路径。supportDimensions:这里只写了三种常用尺寸。卡片 UI 需要针对每个尺寸做适配,否则系统会自动裁剪布局。
2. WidgetFormProvider 生命周期实现
Provider 是卡片运行时的核心,负责处理创建、更新、销毁等事件。
// WidgetFormProvider.ets
import FormExtension from '@ohos.app.form.FormExtension';
import formBinding from '@ohos.app.form.formBinding';
import formInfo from '@ohos.app.form.formInfo';
export default class WidgetFormProvider extends FormExtension {
// 卡片创建时触发
onCreate(want) {
let formId: string = want.parameters[formInfo.FormParam.IDENTITY_KEY] as string;
let dimension: number = want.parameters[formInfo.FormParam.DIMENSION_KEY] as number;
console.info(`[WidgetFormProvider] onCreate called, formId: ${formId}, dimension: ${dimension}`);
let formData = {
'title': '多功能卡片',
'dimension': dimension,
'updateTime': new Date().toLocaleTimeString()
};
return formBinding.createFormBindingData(formData);
}
// 定时更新或触发更新时调用
onUpdate(formId: string) {
console.info(`[WidgetFormProvider] onUpdate called, formId: ${formId}`);
let formData = {
'updateTime': new Date().toLocaleTimeString(),
'refreshCount': new Date().getSeconds()
};
return formBinding.createFormBindingData(formData);
}
// 卡片销毁时调用
onDestroy(formId: string) {
console.info(`[WidgetFormProvider] onDestroy called, formId: ${formId}`);
// 清理定时器或本地缓存
clearFormCache(formId);
}
// 卡片点击事件处理
onEvent(formId: string, message: string) {
console.info(`[WidgetFormProvider] onEvent called, formId: ${formId}, message: ${message}`);
// 处理卡片交互,比如跳转页面
handleCardAction(formId, message);
}
}
function clearFormCache(formId: string): void {
// 实际项目里清理本地存储或资源引用
console.info(`Cache cleared for form: ${formId}`);
}
function handleCardAction(formId: string, message: string): void {
// 通过 AbilityConstant 启动目标页面
console.info(`Handle action: ${message}`);
}
这段代码的关键点:
onCreate返回的FormBindingData决定了卡片首次展示的数据。dimension参数可以用来判断当前尺寸,在 UI 侧做适配。onUpdate由updateDuration定时触发。每次返回新的数据对象,ArkUI 会自动刷新卡片页面。onDestroy必须清理与该卡片相关的资源,否则容易出现内存泄漏。onEvent处理用户点击,通过message参数区分具体操作。
3. 卡片 UI 布局示例
卡片侧需要一个独立的 @Entry 组件来绑定 Provider 返回的数据。
// MultiSizeCard.ets
@Entry
@Component
struct MultiSizeCard {
@State title: string = '卡片'
@State updateTime: string = ''
build() {
Column() {
Text(this.title)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(`更新时间: ${this.updateTime}`)
.fontSize(12)
.fontColor('#666')
}
.width('100%')
.height('100%')
.padding(12)
.backgroundColor('#FFFFFF')
}
}
常见问题
问题 1:updateDuration 配置了但卡片不自动更新
现象:updateDuration 设为 30 或 60,但卡片在桌面上一直不刷新。
原因:这个配置项的单位是分钟,而且系统有最小限制——低于 30 分钟会被忽略。另外,updateEnabled 必须为 true,否则整个更新机制不生效。
解决方案:检查两点——updateEnabled 是否为 true,updateDuration 是否 >= 30。如果不需要频繁更新,建议设置为 60 或更长,避免消耗系统资源。
问题 2:onDestroy 未及时调用导致资源泄漏
现象:在日志中看到卡片被移除后,Provider 进程仍然存活,甚至反复触发 onUpdate。
原因:HarmonyOS 的 Form Kit 对 Provider 进程的销毁有延迟策略。当用户移除卡片时,onDestroy 会立即调用,但 Provider 进程可能还会存在一段时间。如果在 onDestroy 中只打印日志而没有清理资源,定时器或网络连接会继续运行。
解决方案:在 onDestroy 中显式停止所有定时器和网络请求,并使用全局标志位防止回调继续执行。
// 使用全局标志位控制
let isFormActive: Map<string, boolean> = new Map();
// onCreate 时设置
isFormActive.set(formId, true);
// onUpdate 时检查
if (!isFormActive.get(formId)) {
return formBinding.createFormBindingData({});
}
// onDestroy 时清除
isFormActive.set(formId, false);
clearFormCache(formId);
最佳实践
-
合理设置 updateDuration,不要追求极端刷新频率
30 分钟是最小值,频繁更新会加速设备耗电,而且桌面卡片的刷新有系统级节流策略。如果需要实时数据,推荐使用onEvent触发按需更新,而不是拉短定时周期。 -
卡片数据尽量轻量化,避免在 Provider 中做耗时操作
onCreate和onUpdate是在系统进程中被调用的,如果执行网络请求或大量计算,会阻塞卡片响应用户操作。推荐只做数据组装,耗时逻辑放到应用侧通过postCardAction触发。 -
每个尺寸的 UI 必须独立适配,不要依赖系统自动缩放
supportDimensions只是声明了支持的尺寸,但系统不会自动缩放布局。如果一个 2x4 的布局直接用在 1x2 上,内容会被截断。建议在 UI 侧根据dimension参数动态加载不同的布局。
FAQ
Q:为什么真机调试时卡片显示异常,但模拟器正常?
A:模拟器对卡片尺寸的渲染和真机不完全一致。真机上系统状态栏、导航栏会影响实际可用空间。建议真机测试所有支持的尺寸。
Q:用户调整卡片尺寸后,会触发哪个生命周期?
A:尺寸变更不会触发 onCreate 或 onUpdate,而是触发 onCastToDimension 回调(如果 Provider 实现了的话)。你需要在 UI 侧监听 dimension 变化重新布局。
Q:同一个应用可以添加多张相同类型的卡片吗?
A:可以。每张卡片有独立的 formId,Provider 需要按照 formId 分别管理数据。不过 updateDuration 是所有同类型卡片共享的,所有卡片会同时触发 onUpdate。
示例代码地址:项目地址
如果你在卡片配置或生命周期同步上遇到奇怪的问题,建议先检查 form_config.json 的最小更新时长和 updateEnabled 开关,这两个是最高频的失误点。
更多推荐


所有评论(0)