HarmonyOS 实践之应用状态变量共享

news2025/1/15 13:01:24

平时在开发的过程中,我们会在应用中共享数据,在不同的页面间共享信息。虽然常用的共享信息,也可以通过不同页面中组件间信息共享的方式,但有时使用应用级别的状态管理会让开发工作变得简单。

根据不同的使用场景,ArkTS 提供了以下几种应用状态管理的能力:

○ LocalStorage:使用范围在同一页面,页面与卡片和页面与 UIAbility 内部,负责 UI 状态存储。

○ AppStorage:运行时存储,保存在内存中,应用范围全局共享,提供统一的存储供所有页面访问。

○ PersistentStorage:持久化存储,保存在硬盘上,在应用退出或重启后,数据依旧保留。

下面通过简单的程序示例,熟悉一下这三种用法。其中示例程序中包含了以下主要文件:

一、LocalStorage

页面级的 UI 状态存储,同一个页面共享同一个 LocalStorage,不同的页面都可以绑定对应的 LocalStorage。最常用的就是更新服务卡片和跨页面的信息传递。

场景一:更新服务卡片

服务卡片中被 @Entry 装饰的 @Component,可以被分配一个 LocalStorage 实例,在组件内部,通过 @LocalStorageProp 装饰器定义本地变量,并绑定到对应组件上。更新卡片时,先定义一个包含了和 LocalStorageProp 属性同名的参数并放到 formBindingData 中,然后通过 formProvider.updateForm 函数,就可以更新服务卡片了。

我们要在 EntryFormAbility.ets 中通过传递 LocalStorage 改变服务卡片中的默认 Hello 的文本标签为当前时间。

实践步骤:

1.修改服务卡片布局文件,文件开头添加:

let storage = new LocalStorage();

并为 Entry 增加参数 storage。

例如,WidgetCard.ets,默认:

@Entry@Componentstruct WidgetCard {...

改之后:

let storage = new LocalStorage();@Entry(storage)@Componentstruct WidgetCard {...

2.在 EntryFormAbility.ets 中,用装饰器 LocalStorageProp 定义本地变量,装饰器的参数必须要和 formBindingData 中的属性名称相同。

例如,在接收方服务卡片中定义如下:

@LocalStorageProp('localprop') localValue: string = 'Hello';

卡片标签默认显示了 Hello。

在发送方 EntryFormAbility.ts 文件的 onFormEvent 函数里:

onFormEvent(formId, message) {
  let date = new Date();
  let str = date.getHours().toString().padStart(2, '0') + ':' +  date.getMinutes().toString().padStart(2, '0') + ':' + date.getSeconds().toString().padStart(2, '0')
  let formData = {
    'localprop': 'Time: ' + str,
  };
  let formInfo = formBindingData.createFormBindingData(formData)
  formProvider.updateForm(formId, formInfo).then((data) => {
    console.info('FormAbility updateForm success.' + JSON.stringify(data));
  }).catch((error) => {
    console.error('FormAbility updateForm failed: ' + JSON.stringify(error));
  })
}

formData 对象里包含了名称为 localprop 的键值,它通过 formBindingData 由 formProvider 传递给服务卡片,服务卡片接收到该对象后,就自动把该对象赋值给 LocalStorage,相应的 LocalStorageProp 也自动跟着刷新。

这个动作是通过点击卡片上的 update 按钮,触发了 postCardAction 事件从而调用了 onFormEvent 函数,执行结果如下:

场景二:跨页面的信息传递

在页面初次加载时,可以在 EntryAbility.ts 中传递一个 LocalStorage 对象给要打开的页面。

我们打算在 index.ets 页面加载的时候,在 EntryAbility 中传递一个包含 abilitycount 值为 1 的 Storage,页面加载后界面显示该值。

实践步骤:

1.在 EntryAbility.ts 中定义一个 LocalStorage 类型的变量,里面包含 abilitycount 属性。

export default class EntryAbility extends UIAbility {  storage: LocalStorage = new LocalStorage({    'abilitycount': 1  });

在 onWindowStageCreate 函数中,将默认的:

windowStage.loadContent('pages/Index', (err, data) => {

改为传递参数的方式,如下:

windowStage.loadContent('pages/Index', this.storage);

2.在页面端 Index.ets 中,文件开头添加代码来获取共享的 LocalStorage。

let storage = LocalStorage.GetShared()

在结构体内部,通过装饰器 LocalStorageProp 加同样属性名称作为参数,定义一个变量。

@LocalStorageProp('abilitycount') abilityCount: number = 0;

这样名为 abilitycount 的值就通过 LocalStorage 传递到页面了,本地默认的值 0 变为了传递过来的值 1。

下图中 LocalStorage 的值就是页面打开时显示的传递过来的值。

二、AppStorage

全局的 UI 状态存储,在运行时阶段可以在不同的页面间共享信息。我们通过在 Index.ets 页面创建一个变量放到 AppStorage 中,然后分别在 First.ets 页面和 Second.ets 页面访问和修改。

实践步骤:

1.首先在 Index.ets 中,通过 AppStorage 定义一个属性。

AppStorage.SetOrCreate('appcount', 10);

然后,在组件结构体中使用 StorageProp 装饰器定义一个变量,参数为之前定义的 appcount 属性。

@Entry()@Componentstruct Index {

  @StorageProp('appcount') appValue: number = 0;

2.在 First.ets 页面中,通过 StorageProp 定义一个 appValue 变量,关联到 appcount 属性上。

struct First {  @StorageProp('appcount') appValue: number = 0;

在本地修改时,把用户输入的值写入 AppStorage,使用如下语句:

AppStorage.Set('appcount', this.textApp);

Second.ets 页面与 First.ets 页面功能完全相同,主要显示 AppStorage 在不同页面显示和修改的效果。

如下图,主页面、第一个页面和第二个页面初始状态下,读取到的 AppStorage 中的同一个属性的值都是 10。

在第一个页面 First.ets 中把 AppStorage 中的属性值改为 11,我们发现在主页面 Index.ets 和 Second.ets 中,对应的属性值都发生了变化。

同样,在第二个页面 Second.ets 中把 AppStorage 中的属性值改为 12,我们发现在 Index.ets 和 First.ets 中,对应的属性值也都变为了改后的值。

如上测试,我们发现的确可以通过 AppStorage 在不同页面间共享数据。

三、PersistentStorage

持久化存储 UI 状态。保存在 PersistentStorage 中的数据,即使应用退出了,对应的值依然会保留,不是在内存中,而是存储在固定存储介质上的。

我们通过在 Index.ets 页面创建一个属性放到 PersistentStorage 中,然后分别在 First.ets 页面和 Second.ets 页面进行修改,然后再重启应用观察结果。

实践步骤:

1.首先在 Index.ets 中,在 PersistentStorage 里定义一个属性。

PersistentStorage.PersistProp('persistentcount', 100);

然后在组件结构体中,通过装饰器 StorageProp 定义一个属性为 persistentcount 的变量。

@Entry()@Componentstruct Index {  @StorageProp('persistentcount') persistentValue: number = 0;

2.在 First.ets 页面中,我们通过装饰器 StorageProp 定义一个变量绑定 persistentcount 属性。

@Entry@Componentstruct First {  @StorageProp('persistentcount') persistentValue: number = 0;

通过输入框输入新值改变原来存储在 PersistentStorage 的内容。

AppStorage.Set('persistentcount', this.textPersistent);

演示效果如下图,Index.ets 页面,在初始时 AppStorage 和 PersistentStorage 中的对应属性值分别是 10 和 100,在 First.ets 页面中,我们分别改为 11 和 111。

关闭应用,然后重新打开,如下图所示,AppStorage 中的属性值恢复为了 10,PersistentStorage 中的属性值依旧是 111,是改后的值。这证明了 PersistentStorage 有持续化存储的作用。

四、总结

通过这次实践,熟悉了不同的状态变量在应用中的不同应用范围,选用合适的状态变量会让应用开发简单快捷,本地页面内部使用 LocalStorage 保存数据,应用页面间通过 AppStorage 传递信息,PersistentStorage 可以持久化存储数据信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1349060.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SELinux 基本原理

本文讲述 SELinux 保护安全的基本原理 首发公号:Rand_cs 安全检查顺序 不废话,直接先来看张图 当我们执行系统调用的时候,会首先对某些错误情况进行检查,如果失败通常会得到一些 error 信息,通过查看全局变量 errno …

多模态大模型的前世今生

1 引言 前段时间 ChatGPT 进行了一轮重大更新:多模态上线,能说话,会看图!微软发了一篇长达 166 页的 GPT-4V 测评论文,一时间又带起了一阵多模态的热议,随后像是 LLaVA-1.5、CogVLM、MiniGPT-5 等研究工作…

matalb实践(十二):减肥

1.题目 2.解答 2.1模型假设 1.体重增加正比于吸收的热量,平均每8000kcal增加体重1kg 2.身体正常代谢引起的体重减少正比于体重,每周每千克体重消耗热量一般在200kcal至320kcal之间,且因人而异,这相当于体重70kg的人每天消耗2000k…

Feign远程调用丢失请求头问题处理--异步任务执行远程请求线程丢失请求属性问题处理

在关于Feign远程调用丢失请求头问题处理中解决了远程调用发送请求丢失老请求中请求头的问题。A方法接收浏览器中的请求,B方法是A方法中嵌套方法用来发送Feign远程调用。如果B方法是在异步任务CompletableFuture.runAsync(()->{},Executor)中执行并启用线程池分配…

C++多态性——(1)初识多态

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝 苦难和幸福一样,都是生命盛…

HarmonyOS 组件通用属性之通用事件 文档参数讲解(触摸事件)

好 本文 我们来说说触摸事件 字面意思也非常好理解 就是我们手机手指触摸物体触发 我们先在编辑器组件介绍中 找到这个东西的基本用法 Button("跳转").onTouch((event: TouchEvent) > {})最明显的就是 event 的类型变了 点击事件的是 ClickEvent 而这里是 Touc…

【教3妹学编程-算法题】经营摩天轮的最大利润

3妹:“打个中国结,再系个红腰带, 愿善良的人们天天好运来, 你勤劳生活美, 你健康春常在, 你一生的忙碌为了笑逐颜开。” 2哥 : 3妹,元旦快乐啊。 3妹:2哥元旦快乐~。 2哥:祝新的一年,3妹技术突飞…

数据结构与算法之美学习笔记:42 | 动态规划实战:如何实现搜索引擎中的拼写纠错功能?

目录 前言如何量化两个字符串的相似度?如何编程计算莱文斯坦距离?如何编程计算最长公共子串长度?解答开篇 前言 本节课程思维导图: 利用 Trie 树,可以实现搜索引擎的关键词提示功能,这样可以节省用户输入搜…

easyx的窗口函数

文章目录 前言一、EasyX的颜色二、EasyX的坐标和设备1,EasyX的坐标2,EasyX的设备 三、窗口函数1,初始化窗口函数2,关闭绘图窗口3,设置窗口背景板颜色4,清空绘图设备 前言 easyx是针对c的图形库,…

从0到1入门C++编程——02 通讯录管理系统

文章目录 一、创建结构体及菜单显示二、添加联系人三、显示联系人四、删除联系人五、查找联系人六、修改联系人七、清空联系人八、退出通讯录 本文通过C实现一个通讯录管理系统,系统要实现的功能如下。 1、添加联系人:向通讯录中添加新人,信息…

老胡的周刊(第122期)

老胡的信息周刊[1],记录这周我看到的有价值的信息,主要针对计算机领域,内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 🎯 项目 movie-web[2] 开源可自部署的简约在线电影搜…

【MATLAB】鲸鱼算法优化混合核极限学习机(WOA-HKELM)时序预测算法

有意向获取代码,请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 鲸鱼算法优化混合核极限学习机(WOA-HKELM)是一种时序预测算法,它结合了鲸鱼算法和混合核极限学习机(HKELM)的优点。以下是该算法…

解锁React魔法门:高效项目开发工作流揭秘

你好,我是坚持分享干货的 EarlGrey,翻译出版过《Python编程无师自通》、《Python并行计算手册》等技术书籍。 如果我的分享对你有帮助,请关注我,一起向上进击。 创作不易,希望大家给一点鼓励,把公众号设置为…

2024年PMP考试新考纲-PMBOK第七版-【模型、方法和工件】真题解析(2)

今天我们继续来看第七版PMBOK第四部分【模型、方法和工件】这个章节相关的真题。 实际上在做题的时候,可能有的小伙伴会发现,这部分和第六版PMBOK中散落在各个知识领域的题目很相似。没错!在之前版本的PMBOK中,很经典的框架是每个…

2.1 DFMEA步骤一:策划和准备

2.1.1 目的 设计FMEA的“策划和准备”步骤旨在确定将要执行的FMEA类型,以及根据进行中的分析类型(如系统、子系统或组件)明确每个FMEA的范围。设计FMEA(DFMEA)的主要目标包括: 项目识别项目计划:涵盖目的、时间安排、团队、任务和工具(5T)分析边界:界定分析的范围,…

LLM应用的分块策略

每日推荐一篇专注于解决实际问题的外文,精准翻译并深入解读其要点,助力读者培养实际问题解决和代码动手的能力。 欢迎关注公众号 原文标题:Chunking Strategies for LLM Applications 原文地址:https://www.pinecone.io/learn/c…

数据结构:队列(链表和数组模拟实现)

目录 1.何为队列 2.链表模拟实现 2.1 节点和队列创建 2.2 初始化队列 2.3 入队操作 2.4 出队操作 2.5 遍历队列 2.6 获取队首和队尾元素 2.7 判断队列是否为空 2.8 完整实现 3. 数组模拟实现 3.1 创建队列 3.2 入队和出队操作 3.3 遍历队列 3.4 获取队首和队尾元…

计算机组成原理复习4

习题 练习题 下列不属于系统总线的为() a.数据总线 b.地址总线 c.控制总线 d.片内总线 D 系统总线中地址总线的功能是() a.选择主存单元地址 b.选择进行信息传输的设备 c.选择外存地址 d.指定主存和I/O设备接口电路的地址 D 解…

【电商项目实战】商品详情显示与Redis存储购物车信息

🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《电商项目实战》。🎯🎯 &am…

第9章 继承和派生习题(详解)

一、选择题 1.下列表示引用的方法中, () 是正确的。已知:int m10: A.int &xm; B.int &y10; C.int &z; D.fl…