鸿蒙技术分享:鸿蒙页面里更新卡片也太麻烦了吧!!!

🎉🎉🎉怎么简单地在鸿蒙页面内直接更新卡片数据???

服务卡片介绍

Form Kit简介

更新分类

服务卡片有静态卡片和动态卡片之分,而动态卡片的更新逻辑又分为自动更新和手动更新两大类。

  • 定时刷新
  • 定点刷新
  • 下次刷新
  • 代理刷新(最新版本API已不建议使用)
  • 卡片主动更新
  • 页面主动更新

列表前三种其实都是卡片自动更新逻辑,走FormExtensionAbilityonUpdateForm方法。

列表的后三种主要是为了实现在卡片之外的代码中主动刷新的逻辑,比如:

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,大家可以直接拿去用,有问题直接在评论区交流。

相关推荐
Forever_Hopeful10 小时前
华为HarmonyOS NEXT 原生应用开发:页面路由、页面和组件生命周期函数
华为·harmonyos
只是丶很孤单11 小时前
鸿蒙手机文件目录
华为·智能手机·harmonyos
bst@微胖子12 小时前
鸿蒙实现应用通知
华为·harmonyos
二流小码农15 小时前
鸿蒙开发:一个轻盈的上拉下拉刷新组件
android·ios·harmonyos
不懂得小白19 小时前
HarmonyOS 线性容器List 常用的几个方法
开发语言·数据结构·深度学习·华为·list·harmonyos
SuperHeroWu721 小时前
【HarmonyOS】使用AVPlayer播放音乐,导致系统其它应用音乐播放暂停 - 播放音频焦点管理
华为·音视频·harmonyos·avplayer·音频焦点·播放·暂停
纯爱掌门人1 天前
鸿蒙NEXT实践(二):公共事件通信实践-智能节电案例
前端·harmonyos·arkts
刘争Stanley1 天前
纯血鸿蒙崛起,原生Android挑战?两大操作系统巅峰对决,智能设备未来谁主沉浮?
android·华为·kotlin·harmonyos
survivorsfyh1 天前
获取缓存大小与清除 Web 缓存 - 鸿蒙 HarmonyOS Next
缓存·华为·harmonyos·鸿蒙