【共创季稿事节】HarmonyOS7 互动卡片开发实践:EntryFormAbility 如何保存和管理卡片实例
文章目录
- 效果图
- 这篇主要看哪个文件
- onAddForm 做了什么
- 第一步:从 want 里拿系统参数
- 第二步:保存 FormInfo
- 第三步:音乐卡片特殊处理
- 返回初始化数据
- onRemoveForm 也别忘了
- 小白可以自己写一个最小版
- 排查清单
- 写在最后
EntryFormAbility是普通卡片的管家。小白刚接触互动卡片时,最容易忽略它,以为卡片页面写好了就行。
其实不行。桌面上可能同时放了多张音乐卡片、运动卡片、快递卡片。你后面要刷新哪一张?要删除哪一张?要批量更新哪些卡片?这些都要靠EntryFormAbility保存下来的formId。
效果图
这一篇不直接讲动画,而是讲这些效果背后的“实例管理”。只有EntryFormAbility记住每一张桌面卡片,后面点击播放、运动、快递、睡眠状态时,才知道该刷新谁。
先把实例保存清楚,漂亮的互动效果才不会更新错卡片。
这篇主要看哪个文件
打开:
entry/src/main/ets/entryformability/EntryFormAbility.ets它里面有几个核心生命周期:
onAddForm():添加卡片时调用。onUpdateForm():系统请求刷新时调用。onFormEvent():普通卡片发消息时调用。onRemoveForm():移除卡片时调用。onAcquireFormState():返回卡片状态。
这一篇重点看onAddForm()和onRemoveForm()。
onAddForm 做了什么
项目里的代码核心是:
onAddForm(want:Want):formBindingData.FormBindingData{letformId:string='';letformWidth:number=-1;letformHeight:number=-1;if(want.parameters){formId=want.parameters['ohos.extra.param.key.form_identity']asstring;letformName=want.parameters['ohos.extra.param.key.form_name']asstring;letformDimension=want.parameters['ohos.extra.param.key.form_dimension']asstring;formWidth=want.parameters['ohos.extra.param.key.form_width']asnumber;formHeight=want.parameters['ohos.extra.param.key.form_height']asnumber;letformInfo=newFormInfo();formInfo.formId=formId;formInfo.formDimension=formDimension;formInfo.formName=formName;FormUtils.insertFormData(this.context,formInfo);if(formName.includes('Music')){FormUtils.updateMusicControlCard(formId,true);}}returnformBindingData.createFormBindingData({formId:formId,formWidth:formWidth,formHeight:formHeight});}小白先别慌,拆开看。
第一步:从 want 里拿系统参数
添加卡片时,系统会把参数放进want.parameters。项目取了这些字段:
formId=want.parameters['ohos.extra.param.key.form_identity']asstring;letformName=want.parameters['ohos.extra.param.key.form_name']asstring;letformDimension=want.parameters['ohos.extra.param.key.form_dimension']asstring;这三个最重要。
formId:系统给这张卡片分配的唯一 ID。formName:卡片名称,比如MusicCard。formDimension:卡片尺寸,比如2*4。
formId是后续更新卡片的钥匙。没有它,formProvider.updateForm()就不知道更新谁。
第二步:保存 FormInfo
项目创建了一个FormInfo:
letformInfo=newFormInfo();formInfo.formId=formId;formInfo.formDimension=formDimension;formInfo.formName=formName;然后交给FormUtils:
FormUtils.insertFormData(this.context,formInfo);FormUtils内部会调用FormRdbHelper,把这条卡片实例保存到 RDB。
为什么不用数组保存?
因为 Ability 生命周期可能被系统回收。内存数组没了,桌面卡片还在。RDB 更靠谱。
第三步:音乐卡片特殊处理
项目里有一段:
if(formName.includes('Music')){FormUtils.updateMusicControlCard(formId,true);}这段是为了解决一个实际问题:新添加的音乐卡片不知道当前播放状态。
所以添加音乐卡片后,先给这张卡片下发:
isNeedRequestUpdate:true音乐卡片页面里监听到这个字段变化后,会主动向应用请求当前播放数据。
这就是一个很实用的设计:新增卡片不直接猜状态,而是主动请求同步。
返回初始化数据
onAddForm()最后返回:
returnformBindingData.createFormBindingData({formId:formId,formWidth:formWidth,formHeight:formHeight});这些数据会被普通卡片页面通过@LocalStorageProp接收。
比如你可以在卡片里写:
@LocalStorageProp('formId')formId:string='';@LocalStorageProp('formWidth')formWidth:number=0;@LocalStorageProp('formHeight')formHeight:number=0;字段名必须一致。返回里叫formId,卡片里也要叫formId。
onRemoveForm 也别忘了
添加时保存,删除时就要清理:
onRemoveForm(formId:string):void{FormUtils.deleteFormInfo(this.context,formId);}这段很短,但很重要。
如果不删除,数据库里会残留已经不存在的卡片。后面批量更新时,可能会尝试更新一个已经被移除的formId,日志里就会出现各种失败。
小白可以自己写一个最小版
如果你想练习,可以先写一个简化版:
import{formBindingData,FormExtensionAbility}from'@kit.FormKit';importWantfrom'@ohos.app.ability.Want';exportdefaultclassEntryFormAbilityextendsFormExtensionAbility{onAddForm(want:Want):formBindingData.FormBindingData{constparams=want.parameters??{};constformId=params['ohos.extra.param.key.form_identity']asstring;constformName=params['ohos.extra.param.key.form_name']asstring;constformDimension=params['ohos.extra.param.key.form_dimension']asstring;console.info(`add form:${formId},${formName},${formDimension}`);returnformBindingData.createFormBindingData({formId,formName,formDimension});}onRemoveForm(formId:string):void{console.info(`remove form:${formId}`);}}先用这个确认生命周期能跑,再接入项目里的FormUtils和FormRdbHelper。
排查清单
如果onAddForm()没按预期执行,按这个顺序查:
module.json5是否注册了EntryFormAbility,类型是不是form。form_config.json的普通卡片是否配置正确。Index.ets添加卡片时abilityName是否写EntryFormAbility。want.parameters里有没有form_identity、form_name、form_dimension。FormUtils.insertFormData()是否执行成功。
写在最后
EntryFormAbility不写复杂 UI,但它非常关键。它负责把“桌面上的卡片实例”变成项目里可查询、可更新、可删除的数据。
记住一句话:想让卡片后续能刷新,先把formId保存好。
