🎉🎉🎉怎么简单地在鸿蒙页面内直接更新卡片数据???
服务卡片介绍
更新分类
服务卡片有静态卡片和动态卡片之分,而动态卡片的更新逻辑又分为自动更新和手动更新两大类。
- 定时刷新
- 定点刷新
- 下次刷新
- 代理刷新(最新版本API已不建议使用)
- 卡片主动更新
- 页面主动更新
列表前三种其实都是卡片自动更新逻辑,走FormExtensionAbility
的onUpdateForm
方法。
列表的后三种主要是为了实现在卡片之外的代码中主动刷新的逻辑,比如:
1.在卡片上点击了按钮后,更新卡片背景色;
2.在页面中设置卡片背景色,保存后,更新卡片背景色;
卡片主动更新的逻辑可以直接参考官方文档的通过message事件刷新卡片内容和通过router或call事件刷新卡片内容。
而页面主动更新的逻辑在官方文档里并没有明确而详细的说明,本文主要是讲解这部分。
页面主动更新
在页面中更新卡片和通过message
事件更新卡片一样,都需要通过formProvider.updateForm()
方法来进行,只不过区别在于,message
事件触发onFormEvent(formId: string, message: string)
事件,携带了formId
参数。
而在页面中更新卡片时并不知道你要更新的formId
参数。
所以页面主动更新的场景,主要就是解决怎么获取formId
参数的事情。
获取formId
参数
系统的FormExtensionAbility
并没有提供卡片添加到桌面的成功回调方法,所以没办法通过回调直接获取formId
。
FormExtensionAbility
中是定义了onAddForm
方法,但该方法是在添加卡片创建卡片预览时调用的,实际上应该是onCreateForm
。
同时,FormExtensionAbility
中还定义了onRemoveForm
方法,该方法应该是onDestroyForm
,也就是卡片销毁时调用。
所以,当你往桌面添加卡片时,所有的卡片都会触发onAddForm
方法,除了成功添加的卡片之外的卡片都会触发onRemoveForm
方法。
因此我们可以根据这一逻辑,获取到最终添加到桌面的卡片formId
,我们可以保存在preferences中,以备使用。
详情参考以下代码,可以直接拷贝,在项目中继承EasyFormExtensionAbility
:
TypeScript
export interface EasyFormParam {
identity: string;
dimension: number;
name: string;
moduleName: string;
width: number;
height: number;
temporary: boolean;
abilityName: string;
bundleName: string;
launchReason: string;
paramFormCustomize: string;
formRenderingMode: string;
hostBgInverseColor: string;
}
export abstract class EasyFormExtensionAbility extends FormExtensionAbility {
preferences?: preferences.Preferences = undefined
onAddForm(want: Want): formBindingData.FormBindingData {
console.debug(`[卡片]onAddForm`)
const formId = want.parameters?.[formInfo.FormParam.IDENTITY_KEY] as string
let param: EasyFormParam = {
identity: want.parameters?.[formInfo.FormParam.IDENTITY_KEY] as string,
dimension: want.parameters?.[formInfo.FormParam.DIMENSION_KEY] as number,
name: want.parameters?.[formInfo.FormParam.NAME_KEY] as string,
moduleName: want.parameters?.[formInfo.FormParam.MODULE_NAME_KEY] as string,
width: want.parameters?.[formInfo.FormParam.WIDTH_KEY] as number,
height: want.parameters?.[formInfo.FormParam.HEIGHT_KEY] as number,
temporary: want.parameters?.[formInfo.FormParam.TEMPORARY_KEY] as boolean,
abilityName: want.parameters?.[formInfo.FormParam.ABILITY_NAME_KEY] as string,
bundleName: want.parameters?.[formInfo.FormParam.BUNDLE_NAME_KEY] as string,
launchReason: want.parameters?.[formInfo.FormParam.LAUNCH_REASON_KEY] as string,
paramFormCustomize: want.parameters?.[formInfo.FormParam.PARAM_FORM_CUSTOMIZE_KEY] as string,
formRenderingMode: want.parameters?.[formInfo.FormParam.FORM_RENDERING_MODE_KEY] as string,
hostBgInverseColor: want.parameters?.[formInfo.FormParam.HOST_BG_INVERSE_COLOR_KEY] as string,
}
this.preferences = preferences.getPreferencesSync(this.context, { name: 'EasyFormExtensionAbility' })
this.preferences.putSync(formId, param)
let list = this.preferences.getSync('formIdList', new Array()) as Array<string>
list.push(formId)
this.preferences.putSync('formIdList', list)
this.preferences.flush()
// 系统框架的onAddForm实质上是在form创建时调用,这里对名称进行更改,符合原始意图
return this.onCreateFormEasy(formId, param)
}
abstract onCreateFormEasy(formId: string, formParam: EasyFormParam): formBindingData.FormBindingData
onAddFormEasy(formId: string, formParam: EasyFormParam): void {
}
onRemoveForm(formId: string): void {
console.debug(`[卡片]onRemoveForm`)
this.preferences = preferences.getPreferencesSync(this.context, { name: 'EasyFormExtensionAbility' })
let param = this.preferences.getSync(formId, undefined) as EasyFormParam
this.onRemoveFormEasy(formId, param)
this.preferences.deleteSync(formId)
let list = this.preferences.getSync('formIdList', new Array()) as Array<string>
list.splice(list.indexOf(formId), 1)
this.preferences.putSync('formIdList', list)
this.preferences.flush()
}
onRemoveFormEasy(formId: string, formParam: EasyFormParam): void {
}
}
更新卡片
在页面内更新卡片时,通过preferences
获取到所有已添加到桌面的formId
列表。
然后遍历,根据你需要的服务卡片名称,获取到你需要的formId
。
然后根据此formId
调用formProvider.updateForm
更新卡片数据。
详情参考以下代码:
TypeScript
let pref = preferences.getPreferencesSync(getContext(this), { name: 'EasyFormExtensionAbility' })
let list = pref.getSync('formIdList', new Array()) as Array<string>
let formId: string = '';
list.forEach(element => {
let param = pref.getSync(element, undefined) as EasyFormParam
if (param.name === 'service_card_name') {
formId = element
}
});
let info: Record<string, string> = { 'backgroundColor': this.backgroundColor }
try {
class FormDataClass {
info: Record<string, string> = info
}
let formData = new FormDataClass();
let obj: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData);
formProvider.updateForm(formId, obj, (error: BusinessError) => {
if (error) {
console.error(`callback error, code: ${error.code}, message: ${error.message})`);
return;
}
console.log(`formProvider updateForm success`);
});
} catch (error) {
console.error(`catch error, code: ${(error as BusinessError).code}, message: ${(error as BusinessError).message})`);
}
其他:
如果你的一种服务卡片可以在桌面上添加多个,每个有不同的数据,那么你需要自己判断每个formId
的状态,区分进行更新。
总结
官方的FormKit在使用时真的是一言难尽,不但调试运行有很多问题,在API功能的可用性上也很难受。
最大的问题是,可能是因为早期服务卡片的开发不是推广重点,所以文档不全,你去找官方的技术支持人员,他会给你贴一个OpenHarmony的文档......
服务卡片更新确实是刚需,核心代码就是EasyFormExtensionAbility
,大家可以直接拿去用,有问题直接在评论区交流。