首页 > 其他分享 >鸿蒙元服务开发教程03:从底层原理开始讲透桌面卡片的router事件刷新机制

鸿蒙元服务开发教程03:从底层原理开始讲透桌面卡片的router事件刷新机制

时间:2023-09-16 16:01:57浏览次数:41  
标签:03 卡片 UIAbility updateForm let 刷新 router 讲透

相关文章:

鸿蒙元服务开发教程:从底层原理开始讲透桌面卡片的call事件刷新机制

鸿蒙元服务开发教程02:从底层原理开始讲透桌面卡片的message事件刷新机制

首先铺垫两个基础知识:

1.为什么桌面卡片需要使用特殊机制来刷新?

  • 主要有两个原因:第一是HarmonyOS Api9的桌面卡片出于降低系统能耗的目的,被限制了只有5秒的活动时间。超过5秒以后桌面卡片的相关进程会被强制销毁,变成一个静态的页面。只有通过router机制、call机制或者message机制拉起相关后台,才能再次进行卡片内容的刷新。
  • 第二个原因是从实际的运行机制来说,桌面卡片实际上并不是应用主体的一部分,而是归属于鸿蒙系统的桌面所管理的一系列服务,桌面卡片与其对应的应用主体之间相互隔离,只能使用专门的接口来进行数据交互与页面管理。
  • 每张卡片都有一个独立的LocalStorage可以用来存储页面级变量,但同一个LocalStorage的数据只能在UIAbility内部共享,对外隔离,UIAbility无法直接访问。
  • 桌面卡片刷新机制的本质就是通过专门的接口,改变特定桌面卡片的LocalStorage参数。以实现桌面卡片的UI更新。

2.router机制、call机制与message机制有什么不同?

  • 这三个机制都可以用来刷新桌面卡片的,三种机制的数据都以JSON的格式进行配置,并使用formBindingData.createFormBindingData()函数构建数据对象。
  • 主要区别在于:
  • router机制会直接打开应用界面,效果有点像点击桌面图标。也可以带参数打开应用,直接进入应用内部的某个特定位置,或者触发某项功能。更适用于桌面卡片结构复杂或是需要用户参与自定义卡片内容的场景。
  • call机制是不打开应用界面,仅在后台拉起应用主体的UIAbility,来执行UIAbility内部的相关代码。call机制不受5秒时长的限制,可以先实现复杂且费时的数据加载,再提供给桌面卡片进行刷新。
  • message机制则不涉及到应用的UIAbility,只是拉起桌面卡片自己的FormAbility,也可以刷新卡片,但仍然受5秒时长的限制,更适合轻量化的的实现卡片内容的刷新。

接下来进入正式讲解:(本案例使用router机制,拉起FormAbility来刷新卡片内容。)

其实router机制最主要的用处还是从卡片跳转应用主体,有点类似于点击桌面图标的效果,但是因为router可以带参启跳转,能实现直接进入特定页面或者启动特定功能的效果。

router实现卡片刷新效果的机制本质上就是在跳转后由程序自动或是用户手动执行updateForm接口,以刷新卡片内容。

使用router机制刷新卡片的全流程主要分为3个阶段:

  1. (用户点击时)通过卡片的postCardAction接口触发router事件,将需要的信息作为参数提交,由系统启动对应应用的UIAbility→
  2. UIAbility启动成功,onCreateonNewWant生命周期获取到对应的FormID与入参,根据入参直接进行数据准备后通过updateForm接口对指定卡片执行刷新事件/或根据入参启动特定页面,在page页面进行数据准备后通过updateForm接口对指定卡片执行刷新事件→
  3. 卡片page页面接收到数据,更新卡片界面。

由于router机制发送给UIAbility的want中已经包含了卡片信息,因此可以不需要手动传递FormID,直接使用FormInfo接口获取formId。


案例效果展示:

鸿蒙元服务卡片router刷新效果

案例代码:

  1. (用户点击时)通过卡片的postCardAction接口触发router事件,将需要的信息作为参数提交,由系统启动对应应用的UIAbility→

【卡片page的代码】

let storage=new LocalStorage()
@Entry(storage)
@Component
struct WidgetCard {

  @LocalStorageProp('textInfo') textInfo:string='原始文本内容'

  build() {
      Column() {
          Text(this.textInfo)
            .fontColor(Color.Black)
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
      .onClick(() => {
      postCardAction(this, {
        "action": "router",
        "abilityName": 'EntryAbility',
        "params": {
          "detail": ''
        }
      });
    })
  }
}
  1. UIAbility启动成功,onCreate或onNewWant生命周期获取到对应的FormID与入参,根据入参直接进行数据准备后通过updateForm接口对指定卡片执行刷新事件/或根据入参启动特定页面,在page页面进行数据准备后通过updateForm接口对指定卡片执行刷新事件→

【Router后自动刷新的方案】

UIAbility的关键代码:

export default class EntryAbility extends UIAbility {
  onCreate() {
  if (want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) {
      let FormId = want.parameters[formInfo.FormParam.IDENTITY_KEY];//获取formID
      //let message = JSON.parse(want.parameters.params).detail;//读取入参
      let formData = {
        "textInfo": '卡片内容已更新', // 和卡片布局中对应
      };
      let formMsg = formBindingData.createFormBindingData(formData)
      formProvider.updateForm(FormId, formMsg).then((data) => {
        console.info('updateForm success.' + JSON.stringify(data));
      }).catch((error) => {
        console.error('updateForm failed:' + JSON.stringify(error));
      })
    }    
  }
  onNewWant(want){
    if (want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) {
      let FormId = want.parameters[formInfo.FormParam.IDENTITY_KEY];//获取formID
      //let message = JSON.parse(want.parameters.params).detail;//读取入参
      let formData = {
        "textInfo": '卡片内容已更新', // 和卡片布局中对应
      };
      let formMsg = formBindingData.createFormBindingData(formData)
      formProvider.updateForm(FormId, formMsg).then((data) => {
        console.info('updateForm success.' + JSON.stringify(data));
      }).catch((error) => {
        console.error('updateForm failed:' + JSON.stringify(error));
      })
    }
  }
}

【Router后用户手动刷新的方案】

UIAbility的关键代码:

export default class EntryAbility extends UIAbility {
  onNewWant(want){
    if (want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) {
      let FormId = want.parameters[formInfo.FormParam.IDENTITY_KEY];
      //let message = JSON.parse(want.parameters.params).detail;
      AppStorage.SetOrCreate('formId',FormId)//保存当前卡片的FormID
    }
  }
}

Page页的关键代码:

import formBindingData from '@ohos.app.form.formBindingData';
import formProvider from '@ohos.app.form.formProvider';

@Entry
@Component
struct  homepage {
  @State cardText: string = ''
  build() {
    Column(){
      TextInput()
        .onChange((res)=>{
          this.cardText=res
        })
      Button('刷新卡片')
        .onClick(async () => {
          if (AppStorage.Has('formId')) {
            let formId: string = AppStorage.Get('formId')//获取UIAbility保存的FormID
            let formData = {
              "textInfo": this.cardText
            };
            let formMsg = formBindingData.createFormBindingData(formData)
            try {
              await formProvider.updateForm(formId, formMsg)//刷新卡片
              AlertDialog.show({
                message:'卡片刷新成功'
              })
            }
            catch (error) {//失败回调
              AlertDialog.show({
                message:'卡片刷新失败,错误信息:'+JSON.stringify(error)
              })
            }
          } else {
            AlertDialog.show({
              message: '请先添加卡片'
            })
          }
        })
    }
    .width('100%')
    .height('100%')
  }
}
  1. 卡片page页面接收到数据,更新卡片界面。

【即1.的代码,updateForm成功后会根据LocalStorage中特定参数的变化会自动刷新】

let storage=new LocalStorage()
@Entry(storage)
@Component
struct WidgetCard {

  @LocalStorageProp('textInfo') textInfo:string='原始文本内容'//localStorage变化后自动同步,更新UI

  build() {
      Column() {
          Text(this.textInfo)
            .fontColor(Color.Black)
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
      .onClick(() => {
      postCardAction(this, {
        "action": "router",
        "abilityName": 'EntryAbility',
        "params": {
          "detail": ''
        }
      });
    })
  }
}

postCardAction接口router事件的写法如下:

鸿蒙元服务开发教程03:从底层原理开始讲透桌面卡片的router事件刷新机制_桌面卡片

鸿蒙元服务开发教程03:从底层原理开始讲透桌面卡片的router事件刷新机制_harmonyOS_02

updateForm接口的写法如下:

鸿蒙元服务开发教程03:从底层原理开始讲透桌面卡片的router事件刷新机制_元服务_03

标签:03,卡片,UIAbility,updateForm,let,刷新,router,讲透
From: https://blog.51cto.com/u_16236731/7494264

相关文章

  • nio---io区别 20230403
    文件的抽象化表示,字节流以及字符流的文件操作等属于传统IO的相关内容,我们已经在前面的文章进行了较为深刻的学习了。但是传统的IO流还是有很多缺陷的,尤其它的阻塞性加上磁盘读写本来就慢,会导致CPU使用效率大大降低。所以,jdk1.4发布了NIO包,NIO的文件读写设计颠覆了传统I......
  • python03
    2.编程初体验编程必须保存保存和打开一致否则就会乱码。默认Python解释器都是以UTF-8编码形式打开文件。如果想要修改Python的默认解释器编码,可以这样#-*-coding:gbk-*- 建议所有Python代码文件都要以UTF-8编码保存和读取。3.输出将结果或内容想要呈现给用户关......
  • 《LINUX设备驱动程序》学习笔记 ——03
    1.学习模块前的一些基础知识头文件:内核是一个特定的环境,对需要和它接口的代码有其自己的一些要求,所以大部分的模块代码中都会包含相当数量的头文件,其中有几个头文件是专门用于模块的,因此会出现在每个可装载的模块中:#include<linux/module.h>#include<linux/init.h>......
  • Codeforces Global Round 17 A. Anti Light's Cell Guessing
    给一个\(n\timesm\)的网格,里面藏了一个炸弹\((x_0,y_0)\)。你可以选择\(k\)个坐标\((x_1,y_1),(x_2,y_2),\cdots,(x_k,y_k)\)。第\(i\)次选择计算机会回复你一个数\(d_i=|x_0-x_i|+|y_0-y_i|\)。至少需要选出多少个坐标才能确定\((x_0,y_0)\)的位......
  • 米联客MLK_CA03核心模块硬件手册
    1产品概述随着科技的发展,现有的数字产品已经不能满足人们在通信基础设施、医疗电子、工业控制等行业的需求,设计出更高的处理带宽,更广的应用范围、更低的使用功耗的芯片成为芯片厂商的追求。安路科技PH1A系列FPGA包含更多逻辑单元、高速串行的I/O、丰富的存储资源和IP资源,定......
  • Vue项目报TypeError: Cannot read properties of undefined (reading '_wrapper')
    前情最近在做一个营销活动的时候,我选择了Vue技术栈来开发。坑位项目看似一切都正常,但当我在绑定的js事件中去修改当前组件的data上的值时会报错:TypeError:Cannotreadpropertiesofundefined(reading'_wrapper')。报错信息指向vue.runtime.esm.js,不太好定位,一度怀疑是不......
  • python中'\n'与'r'的区别和使用习惯
    在Python中,'\n'和'\r'是两个特殊的转义字符,它们用于控制字符串中的换行和回车行为。它们有不同的含义和用途:'\n'(换行符):'\n'表示换行,在字符串中使用它会将光标移动到下一行的行首。通常用于在文本中创建新的行或在输出中添加换行符,以使文本更易于阅读。示例:print("这是第一行\n这是......
  • DBeaver连接国产数据库OceanBase,以及Python连接,解决ModuleNotFoundError: No module n
    DBeaver连接OceanBase参考:https://www.modb.pro/db/365929用户名的格式为:数据库用户名@租户名#集群名 Python连接OceanBase参考:https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000000033288pip3installJayDeBeApi会自动下载JayDeBeApi和JPype1两个......
  • 03常量+注释
    1常量是什么固定不变的量2定义常量因为python中没有严格意义上的常量,如果你非要改,也可以,一定要记住,常量是约定俗成的,但是也可以更改,但是最好不要改。变量名必须大写。FANPING_HEIGHT=150#FANPING_HEIGHT=FANPING_HEIGHT+1#print(FANPING_HEIGHT)1513注释......
  • UnicodeEncodeError: 'gbk' codec can't encode character '\ufffd' in positio
    写入文件报错UnicodeEncodeError:'gbk'codeccan'tencodecharacter'\ufffd'inposition2494:illegalmultibytesequence 解决方法  withopen('./abc.html','w',encoding='utf-8')asfp: fp.write(respone......