卡片数据交互说明
ArkTS卡片框架提供了updateForm接口和requestForm()接口主动触发卡片的页面刷新,通过LocalStorageProp确认需要刷新的卡片数据。
接口 | 是否系统能力 | 约束 |
---|---|---|
updateForm | 否 | 1. 提供方调用。 2. 提供方仅允许刷新自己的卡片,其他提供方的卡片无法刷新。 |
requestForm | 是 | 1. 使用方调用。 2. 仅允许刷新添加到当前使用方的卡片,添加到其他使用方的卡片无法刷新。 |
卡片定时刷新和定点刷新
当前卡片框架提供了如下几种按时间刷新卡片的方式:
-
定时刷新:表示在一定时间间隔内调用onUpdateForm的生命周期回调函数自动刷新卡片内容。可以在form_updatebytime_config.json配置文件的updateDuration字段中进行设置。例如,可以将刷新时间设置为每小时一次。
-
在使用定时和定点刷新功能之前,需要在form_config.json配置文件中设置updateEnabled字段为true,以启用周期性刷新功能。
当配置了updateDuration(定时刷新)后,该设置会优先于scheduledUpdateTime(定点刷新)生效,即使同时配置了两者,定点刷新也会被忽略。
-
为减少卡片被动周期刷新进程启动次数,降低卡片刷新功耗,应用市场在安装应用时可以为该应用配置刷新周期,
也可以为已经安装的应用动态配置刷新周期,用来限制卡片刷新周期的时长,以达到降低周期刷新进程启动次数的目的。
● 当配置了updateDuration(定时刷新)后,若应用市场动态配置了该应用的刷新周期,
卡片框架会将form_config.json文件中配置的刷新周期与应用市场配置的刷新周期进行比较,取较长的刷新周期做为该卡片的定时刷新周期。
● 若应用市场未动态配置该应用的刷新周期,则以form_config.json文件中配置的刷新周期为准。
● 若该卡片取消定时刷新功能,该规则将无效。
● 卡片定时刷新的更新周期单位为30分钟。应用市场配置的刷新周期范围是1~336,即最短为半小时(1 * 30min)刷新一次,最长为一周(336 * 30min)刷新一次。
● 该规则从API11开始生效。若小于API11,则以form_config.json文件中配置的刷新周期为准。
{ "forms": [ { "name": "UpdateDuration", "description": "$string:widget_updateduration_desc", "src": "./ets/updateduration/pages/UpdateDurationCard.ets", "uiSyntax": "arkts", "window": { "designWidth": 720, "autoDesignWidth": true }, "colorMode": "auto", "isDefault": true, "updateEnabled": true, "scheduledUpdateTime": "10:30", "updateDuration": 2, "defaultDimension": "2*2", "supportDimensions": [ "2*2" ] } ] }
-
-
定点刷新:表示在每天的某个特定时间点自动刷新卡片内容。可以在form_updatebytime_config.json配置文件中的scheduledUpdateTime字段中进行设置。例如,可以将刷新时间设置为每天的上午10点30分。
当同时配置了定时刷新(updateDuration)和定点刷新(scheduledUpdateTime)时,定时刷新的优先级更高。如果想要配置定点刷新,则需要将updateDuration配置为0。
{ "forms": [ { "name": "ScheduledUpdateTime", "description": "$string:widget_scheupdatetime_desc", "src": "./ets/scheduledupdatetime/pages/ScheduledUpdateTimeCard.ets", "uiSyntax": "arkts", "window": { "designWidth": 720, "autoDesignWidth": true }, "colorMode": "auto", "isDefault": true, "updateEnabled": true, "scheduledUpdateTime": "10:30", "updateDuration": 0, "defaultDimension": "2*2", "supportDimensions": [ "2*2" ] } ] }
-
下次刷新:表示指定卡片的下一次刷新时间。可以通过调用ssetFormNextRefreshTime接口来实现。最短刷新时间为5分钟。例如,可以在接口调用后的5分钟内刷新卡片内容。
import { FormExtensionAbility, formProvider } from '@kit.FormKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { BusinessError } from '@kit.BasicServicesKit'; const TAG: string = 'UpdateByTimeFormAbility'; const FIVE_MINUTE: number = 5; const DOMAIN_NUMBER: number = 0xFF00; export default class UpdateByTimeFormAbility extends FormExtensionAbility { onFormEvent(formId: string, message: string): void { // Called when a specified message event defined by the form provider is triggered. hilog.info(DOMAIN_NUMBER, TAG, `FormAbility onFormEvent, formId = ${formId}, message: ${JSON.stringify(message)}`); try { // 设置过5分钟后更新卡片内容 formProvider.setFormNextRefreshTime(formId, FIVE_MINUTE, (err: BusinessError) => { if (err) { hilog.info(DOMAIN_NUMBER, TAG, `Failed to setFormNextRefreshTime. Code: ${err.code}, message: ${err.message}`); return; } else { hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in setFormNextRefreshTiming.'); } }); } catch (err) { hilog.info(DOMAIN_NUMBER, TAG, `Failed to setFormNextRefreshTime. Code: ${(err as BusinessError).code}, message: ${(err as BusinessError).message}`); } } ... }
在触发定时、定点或下次刷新后,系统会调用FormExtensionAbility的onUpdateForm生命周期回调,在回调中,可以使用updateForm进行提供方刷新卡片
-
定时刷新有配额限制,每张卡片每天最多通过定时方式触发刷新50次,定时刷新包含卡片配置项updateDuration和调用setFormNextRefreshTime方法两种方式,当达到50次配额后,无法通过定时方式再次触发刷新,刷新次数会在每天的0点重置。
-
当前定时刷新使用同一个计时器进行计时,因此卡片定时刷新的第一次刷新会有最多30分钟的偏差。比如第一张卡片A(每隔半小时刷新一次)在3点20分添加成功,定时器启动并每隔半小时触发一次事件,第二张卡片B(每隔半小时刷新一次)在3点40分添加成功,在3点50分定时器事件触发时,卡片A触发定时刷新,卡片B会在下次事件(4点20分)中才会触发。
-
定时刷新和定点刷新仅在屏幕亮屏情况下才会触发,在灭屏场景下仅会记录刷新动作,待亮屏时统一进行刷新。
-
如果使能了卡片代理刷新,定时刷新和下次刷新不生效。
卡片代理刷新
卡片代理刷新是一种通过系统应用刷新卡片的机制。卡片提供方不在运行时,仍然可以通过开启了数据共享能力的系统应用完成卡片数据的更新。
实现原理
图1 代理刷新运行原理
如图1,与ArkTS卡片实现原理图相比,卡片代理刷新原理新增了数据管理服务和数据提供方。
- 数据管理服务:该场景下主要提供了多应用间的数据共享的机制。
- 数据提供方(仅支持系统应用):系统应用作为数据提供方,需要开启数据共享能力,同时需要自定义key + subscriberId作为共享数据的标识。
只有系统提供了作为数据提供方的应用,同时提供公开可获得的共享数据标识,才能正常使用该特性。
卡片提供方处理流程(图中蓝色箭头):
-
卡片提供方在卡片提供方的配置文件form_config.json中配置dataProxyEnabled字段为true,以开启卡片代理刷新功能。
说明
卡片代理刷新开启后,定时刷新和下次刷新失效。
-
卡片提供方在onAddForm回调中,把数据提供方定义的key + subscriberId返回给卡片管理服务。
-
卡片管理服务解析卡片提供方的订阅信息,并向数据管理服务注册订阅实例。
卡片代理刷新运行流程(图中红色箭头):
- 数据提供方以key + subscriberId作为数据的标识,将数据存储到数据库。
- 数据管理服务感知到数据库变化,将新的数据发布给当前注册的所有订阅实例。
- 卡片管理服务从订阅实例中解析出数据,发送给卡片渲染服务。
- 卡片渲染服务运行卡片页面代码widgets.abc,widgets.abc按新数据进行渲染,并将渲染后的数据发送至卡片使用方对应的卡片组件。
数据提供方提供的共享数据有两种类型:
-
过程数据,不会一直存储,有老化期,所有应用都可以订阅。
-
持久化数据,仅系统应用可以订阅。
相应的卡片代理刷新配置有所不同,下面分别介绍具体开发方式。
卡片提供方开发(过程数据)
-
配置form_config.json文件中的dataProxyEnabled字段为true,以启用卡片代理刷新功能,当订阅的过程数据更新时,系统会自动更新卡片数据。
{ "forms": [ { "name": "WidgetProcessData", "description": "$string:ProcessDataEntryAbility_desc", "src": "./ets/widgetprocessdata/pages/WidgetProcessDataCard.ets", "uiSyntax": "arkts", "window": { "designWidth": 720, "autoDesignWidth": true }, "colorMode": "auto", "isDefault": true, "updateEnabled": true, "scheduledUpdateTime": "10:30", "defaultDimension": "2*2", "supportDimensions": [ "2*2" ], "dataProxyEnabled": true } ] }
-
在onAddForm回调中配置订阅信息proxyData,并通过formBinding返回给卡片管理服务。示例中将key设置为"datashareproxy://com.samples.widgetupdatebyproxy/weather",subscriberId设置为"11"。
key可以是uri也可以是简单字符串,subscriberId默认值为当前formId,实际取值都依赖于数据发布方的定义。
import { formBindingData, FormExtensionAbility } from '@kit.FormKit'; import { Want } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; const TAG: string = 'ProcessDataFormAbility'; const DOMAIN_NUMBER: number = 0xFF00; export default class ProcessDataFormAbility extends FormExtensionAbility { onAddForm(want: Want): formBindingData.FormBindingData { let formData: Record<string, Object> = {}; let proxies: formBindingData.ProxyData[] = [ { key: 'datashareproxy://com.samples.widgetupdatebyproxy/weather', subscriberId: '11' } ]; let formBinding = formBindingData.createFormBindingData(formData); formBinding.proxies = proxies; hilog.info(DOMAIN_NUMBER, TAG, 'onAddForm'); return formBinding; } }
-
在卡片页面文件卡片页面文件卡片页面文件中,通过LocalStorage变量获取订阅到的数据,LocalStorage绑定了一个字符串,以key:value的键值对格式来刷新卡片订阅数据,其中key必须与卡片提供方订阅的key保持一致。示例中,通过'city'获取订阅的数据,并在Text组件显示。
let storageProcess = new LocalStorage(); @Entry(storageProcess) @Component struct WidgetProcessDataCard { @LocalStorageProp('datashareproxy://com.samples.widgetupdatebyproxy/weather') city: ResourceStr = $r('app.string.loading'); build() { Column() { Column() { Text(this.city) .fontColor('#FFFFFF') .opacity(0.9) .fontSize(14) .margin({ top: '8%', left: '10%' }) }.width('100%') .alignItems(HorizontalAlign.Start) }.width('100%').height('100%') .backgroundImage($r('app.media.CardEvent')) .backgroundImageSize(ImageSize.Cover) } }
卡片提供方开发(持久化数据,仅对系统应用开放)
-
配置form_config.json文件中的dataProxyEnabled字段为true,以启用卡片代理刷新功能。
{ "forms": [ { "name": "WidgetPersistentData", "description": "This is a service widget update by proxy using persistent data.", "src": "./ets/widgetpersistentdata/pages/WidgetPersistentDataCard.ets", "uiSyntax": "arkts", "window": { "designWidth": 720, "autoDesignWidth": true }, "colorMode": "auto", "isDefault": true, "updateEnabled": true, "scheduledUpdateTime": "10:30", "updateDuration": 1, "defaultDimension": "2*2", "supportDimensions": [ "2*2" ], "dataProxyEnabled": true } ] }
-
在onAddForm回调中添加订阅模板addTemplate,通过模板谓词告诉数据库订阅的数据条件。然后配置订阅信息proxyData,并通过formBinding返回给卡片管理服务。示例中将谓词设置为"list" : "select type from TBL00 limit 0,1",表示从TBL00数据库中获取type列的第一条数据,数据将会以{"list":[{"type":"value0"}]}格式返回到卡片页面代码widgets.abc中。当订阅的持久化数据更新时,系统会自动更新卡片数据。
- key的取值是uri,依赖于数据发布方定义。
- subscriberId可自定义,addTemplate中的subscriberId参数与proxies.subscriberId保持一致即可。
import { formBindingData, FormExtensionAbility } from '@kit.FormKit'; import { Want } from '@kit.AbilityKit'; import { dataShare } from '@kit.ArkData'; export default class PersistentDataFormAbility extends FormExtensionAbility { onAddForm(want: Want): formBindingData.FormBindingData { let subscriberId = '111'; let template: dataShare.Template = { predicates: { 'list': `select type from TBL00 where cityId = ${subscriberId}` }, scheduler: '' }; dataShare.createDataShareHelper(this.context, 'datashareproxy://com.samples.widgetupdatebyproxy', { isProxy: true }).then((data) => { let dataShareHelper = data; dataShareHelper.addTemplate('datashareproxy://com.samples.widgetupdatebyproxy/test', subscriberId, template); }); let formData: Record<string, Object> = {}; let proxies: formBindingData.ProxyData[] = [ { key: 'datashareproxy://com.samples.widgetupdatebyproxy/test', subscriberId: subscriberId } ]; let formBinding: formBindingData.FormBindingData = { data: JSON.stringify(formData), proxies: proxies }; return formBinding; } }
-
在卡片页面文件中,通过LocalStorage变量获取订阅到的数据,LocalStorage绑定了一个字符串,以key:value的键值对格式来刷新卡片订阅数据,其中key必须与卡片提供方订阅的key保持一致。示例中,通过'list'获取订阅的数据,并把第一个元素的值显示在Text组件上。
let storagePersis = new LocalStorage(); @Entry(storagePersis) @Component struct WidgetPersistentDataCard { readonly FULL_WIDTH_PERCENT: string = '100%'; readonly FULL_HEIGHT_PERCENT: string = '100%'; @LocalStorageProp('list') list: Record<string, string>[] = [{ 'type': 'a' }]; build() { Column() { Column() { Text((this.list[0]['type'])) .fontColor('#FFFFFF') .opacity(0.9) .fontSize(14) .margin({ top: '8%', left: '10%' }) }.width('100%') .alignItems(HorizontalAlign.Start) }.width(this.FULL_WIDTH_PERCENT).height(this.FULL_HEIGHT_PERCENT) .backgroundImage($r('app.media.CardEvent')) .backgroundImageSize(ImageSize.Cover) } }
最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?但是又不知道从哪里下手,而且学习时频繁踩坑,最终浪费大量时间。所以本人整理了一些比较合适的鸿蒙(HarmonyOS NEXT)学习路径和一些资料的整理供小伙伴学习
点击领取→纯血鸿蒙Next全套最新学习资料希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取~~
一、鸿蒙(HarmonyOS NEXT)最新学习路线
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)…等技术知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
二、HarmonyOS Next 最新全套视频教程
三、《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
四、大厂面试必问面试题
五、鸿蒙南向开发技术
六、鸿蒙APP开发必备
完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。