文章目录先搞明白谁在控制刷新方式一定时刷新updateDuration方式二定点刷新scheduledUpdateTime方式三主动请求刷新formHost.requestForm三种方式对比卡片 UI 接收数据整体数据流图常见问题写在最后写卡片刷新功能踩了不少坑最大的问题是刷新方式有三种文档描述很相似一不小心配错了卡片数据死活不更新死活不知道原因。今天把这三种方式彻底讲清楚。先搞明白谁在控制刷新刷新卡片数据的流程是这样的触发刷新可能是定时器、定点时间、宿主应用按钮系统回调FormExtensionAbility.onUpdateForm(formId)你在里面构造新数据调formProvider.updateForm(formId, newData)推送卡片 UI 收到LocalStorage更新自动重渲染三种刷新方式的区别只在第 1 步——触发方式不同后面都一样。方式一定时刷新updateDuration最简单设置一个刷新间隔系统自动按时来敲门。在form_config.json里配置{forms:[{name:widget,updateEnabled:true,// 必须是 true否则全部刷新功能都不生效updateDuration:1,// 单位30分钟填 1 每30分钟刷一次scheduledUpdateTime:// 定时刷新时此字段留空或不填}]}注意updateDuration的单位比较坑不是分钟也不是秒是30分钟的倍数updateDuration 值实际刷新间隔130 分钟260 分钟1小时4824 小时系统最短刷新间隔是 30 分钟不能更短了这是平台限制。FormAbility 里处理刷新// entry/src/main/ets/entryformability/EntryFormAbility.etsimport{formBindingData,FormExtensionAbility,formProvider}fromkit.FormKit;import{Want}fromkit.AbilityKit;import{BusinessError}fromkit.BasicServicesKit;exportdefaultclassEntryFormAbilityextendsFormExtensionAbility{onAddForm(want:Want):formBindingData.FormBindingData{// 卡片创建时返回初始数据constformData:Recordstring,string{};returnformBindingData.createFormBindingData(formData);}onUpdateForm(formId:string):void{// 系统按照 updateDuration 的间隔自动调用这个方法// 在这里准备新数据然后推送给卡片classFormDataClass{title:stringTitle Update.;// 对应卡片 UI 里的 title 绑定detail:stringDescription update success.;// 对应卡片 UI 里的 detail 绑定}constformDatanewFormDataClass();constformInfoformBindingData.createFormBindingData(formData);// 关键用 formProvider.updateForm 推送数据formProvider.updateForm(formId,formInfo).then((){console.info(定时刷新成功);}).catch((error:BusinessError){console.error(定时刷新失败:${JSON.stringify(error)});});}}方式二定点刷新scheduledUpdateTime在每天固定的时间点刷一次比如每天上午 10:30 更新。修改form_config.json{forms:[{name:widget,updateEnabled:true,updateDuration:0,// 定点刷新时updateDuration 要设为 0scheduledUpdateTime:10:30// 每天 10:30 刷新24小时制}]}注意updateDuration和scheduledUpdateTime是互斥的。想用定点刷新updateDuration必须设为0。onUpdateForm的代码和定时刷新完全一样只是触发的时间点不同。方式三主动请求刷新formHost.requestForm前两种是系统主动来找你这种是宿主应用卡片使用方主动要求刷新。典型场景用户在应用里点了刷新按钮你希望卡片立马更新数据。宿主应用FormUpdateDemo的 Index 页面// entry/src/main/ets/pages/Index.etsimport{formHost}fromkit.FormKit;import{BusinessError}fromkit.BasicServicesKit;import{hilog}fromkit.PerformanceAnalysisKit;constDOMAIN_NUMBER:number0xFF00;letstoragenewLocalStorage();Entry(storage)Componentstruct Index{StateformId:string0;// 这个 ID 要从 FormComponent 的 onAcquired 回调里取build(){Column(){// FormComponent 展示卡片同时获取 formIdFormComponent({id:0,name:widget,bundle:com.samples.formupdatedemo,ability:EntryFormAbility,module:entry,dimension:2,temporary:false,}).size({width:200,height:200}).borderColor(Color.Black).borderRadius(10).borderWidth(1)// 卡片成功加载后拿到 formId.onAcquired((form:FormCallbackInfo){hilog.info(DOMAIN_NUMBER,testTag,onAcquired:${JSON.stringify(form)});this.formIdform.id.toString();// 保存 formId后续刷新用}).onRouter((){hilog.info(DOMAIN_NUMBER,testTag,onRouter);}).onError((error){hilog.error(DOMAIN_NUMBER,testTag,onError:${JSON.stringify(error)});})Text(当前 formId:${this.formId}).fontSize(14).margin(10)// 点击按钮主动请求刷新Button(刷新卡片).onClick((){if(this.formId!0){// formHost.requestForm 触发 onUpdateForm 回调formHost.requestForm(this.formId).then((){hilog.info(DOMAIN_NUMBER,testTag,主动请求刷新成功);}).catch((error:BusinessError){hilog.error(DOMAIN_NUMBER,testTag,刷新失败:${error?.code}${error?.message});});}}).margin(5).width(50%)}.width(100%).height(100%)}}流程重点先从FormComponent.onAcquired拿到formId再用formHost.requestForm(formId)触发刷新。如果没拿到formId就调用直接报错。三种方式对比方式触发者配置位置最小间隔适用场景定时刷新系统form_config.jsonupdateDuration30分钟定期更新天气、新闻等定点刷新系统form_config.jsonscheduledUpdateTime每天一次每日早报、定时提醒主动请求宿主应用代码调用无限制用户手动触发、实时数据卡片 UI 接收数据三种方式在FormAbility里最终都调用formProvider.updateForm卡片 UI 通过LocalStorageProp接收更新后的数据// entry/src/main/ets/widget/pages/WidgetCard.etsletstorage:LocalStoragenewLocalStorage();Entry(storage)Componentstruct WidgetCard{// 这两个字段名要和 FormAbility 里 FormDataClass 的字段名完全一致LocalStorageProp(title)title:string加载中...;LocalStorageProp(detail)detail:string;build(){Column(){Text(this.title).fontSize(16).fontColor(#FFFFFF).margin({top:8%,left:10%})Text(this.detail).fontSize(12).fontColor(#FFFFFF).opacity(0.6).margin({top:5%,left:10%})}.width(100%).height(100%)}}整体数据流图常见问题QupdateEnabled设成false了但是requestForm还能用吗不能用。updateEnabled是总开关关掉之后所有刷新方式包括主动请求都会被拦截onUpdateForm不会被调用。Q定时刷新和定点刷新能同时配吗不能。两个配置互斥同时填了系统只会用其中一种通常是scheduledUpdateTime优先。Q卡片在后台不可见时还会刷新吗不会系统为了省电不可见的卡片不会触发onUpdateForm。等卡片重新可见时会触发一次刷新。写在最后这三种方式各有用途别混用。想让卡片自动更新天气、股价用定时刷新想让卡片每天固定时间更新日报用定点刷新想让用户点按钮立刻刷新就用formHost.requestForm。选对了方式卡片就省电又好用。