【最新鸿蒙应用开发】——数据存储?持久化?

数据存储

鸿蒙应用中的关于数据存储这块,分为应用状态管理存储还有一些数据持久化存储,不清楚概念的可以看我之前的前两篇文章,这边主要帮助大家区别一下状态存储和数据持久化存储的区别,避免概念和使用场景混淆。

1. localStorage和appStorage的区别,和对应的装饰器

LocalStorage

localStorage是页面级数据存储,在页面中创建实例,组件中使用@LocalStorageLink和@LocalStorageProp装饰器修饰对应的状态变量,绑定对应的组件使用比状态属性更灵活

//应用逻辑使用LocalStorage
let para: Record<string,number> = { 'PropA': 47 };
let storage: LocalStorage = new LocalStorage(para); // 创建新实例并使用给定对象初始化 , 创建实例存储数据
let propA: number | undefined = storage.get('PropA') // propA == 47 ,get()获取数据
//link():如果给定的propName在LocalStorage实例中存在,则返回与LocalStorage中propName对应属性的双向绑定数据。 (双向同步)
let link1: SubscribedAbstractProperty<number> = storage.link('PropA'); // link1.get() == 47
let link2: SubscribedAbstractProperty<number> = storage.link('PropA'); // link2.get() == 47
//prop():如果给定的propName在LocalStorage中存在,则返回与LocalStorage中propName对应属性的单向绑定数据。  (单向同步)
let prop: SubscribedAbstractProperty<number> = storage.prop('PropA'); // prop.get() == 47
link1.set(48); // two-way sync: link1.get() == link2.get() == prop.get() == 48 //双向同步
prop.set(1); // one-way sync: prop.get() == 1; but link1.get() == link2.get() == 48 //单向同步
link1.set(49); // two-way sync: link1.get() == link2.get() == prop.get() == 49
  • new LocalStorage(数据Object)创建实例并存储数据

  • set方法,设置数据

  • get方法,获取数据

  • link方法,返回一个双向同步的变量

    • 与UI逻辑中@LocalStorageLink装饰器类似

  • prop方法,返回单向同步的变量

    • 与UI逻辑中@LocalStorageProp装饰器类似

//UI使用LocalStorage
//除了应用程序逻辑使用LocalStorage,还可以借助LocalStorage相关的两个装饰器@LocalStorageProp和@LocalStorageLink,在UI组件内部获取到LocalStorage实例中存储的状态变量。
// 创建新实例并使用给定对象初始化
let para: Record<string, number> = { 'PropA': 47 };
//这个变量一般就定义在某个@Entry组件的上方**
let storage: LocalStorage = new LocalStorage(para);
​
@Component
struct Child {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageLink('PropA') storageLink2: number = 1;
​build() {Button(`Child from LocalStorage ${this.storageLink2}`)// 更改将同步至LocalStorage中的'PropA'以及Parent.storageLink1.onClick(() => {this.storageLink2 += 1})}
}
// 使LocalStorage可从@Component组件访问
@Entry(storage)//storage是上边定义的变量**
@Component
struct Parent {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageLink('PropA') storageLink1: number = 1;
​build() {Column({ space: 15 }) {Button(`Parent from LocalStorage ${this.storageLink1}`) // initial value from LocalStorage will be 47, because 'PropA' initialized already.onClick(() => {this.storageLink1 += 1})// @Component子组件自动获得对CompA LocalStorage实例的访问权限。Child()}}
}
//上述代码:如果将LocalStorageLink改为LocalStorageProp就由双向变为了单向
  • new LocalStorage(数据Object)创建实例并存储数据

  • 父组件:

    • @Entry(LocalStorage实例) , 将LocalStorage数据注册到页面中,使得页面内部可以使用数据

    • @LocalStorageLink ,将页面变量与数据进行双向绑定,父子组件都可以使用

    • @LocalStorageProp,将页面变量与数据进行单向绑定,父子组件都可以使用

AppStorage

appStorage是进程级数据存储(==应用级的全局状态共享==),进程启动时自动创建了唯一实例,在各个页面组件中@StorageProp和@StorageLink装饰器修饰对应的状态变量。

//AppStorage是单例,它的所有API都是静态的
AppStorage.setOrCreate('PropA', 47);
​
let propA: number | undefined = AppStorage.get('PropA') // propA in AppStorage == 47
let link1: SubscribedAbstractProperty<number> = AppStorage.link('PropA'); // link1.get() == 47
let link2: SubscribedAbstractProperty<number> = AppStorage.link('PropA'); // link2.get() == 47
let prop: SubscribedAbstractProperty<number> = AppStorage.prop('PropA'); // prop.get() == 47
​
link1.set(48); // two-way sync: link1.get() == link2.get() == prop.get() == 48
prop.set(1); // one-way sync: prop.get() == 1; but link1.get() == link2.get() == 48
link1.set(49); // two-way sync: link1.get() == link2.get() == prop.get() == 49
​
AppStorage.get<number>('PropA') // == 49
link1.get() // == 49
link2.get() // == 49
prop.get() // == 49
  • 语法基本上与LocalStorage类似,只不过是静态方法

  • link双向,prop单向

AppStorage.setOrCreate('PropA', 47);
​
@Entry(storage)
@Component
struct CompA {@StorageLink('PropA') storageLink: number = 1;
​build() {Column({ space: 20 }) {Text(`From AppStorage ${this.storageLink}`).onClick(() => {this.storageLink += 1})}}
}
  • @StorageLink换为@StorageProp,双向就变为单向的了

  • 不建议使用@StorageLink , 其实就是因为AppStorage共享范围太多,更新效率低下,也可能造成不必要的更新

localStorage和appStorage数据存取都是在主线程进行的,且api只提供了同步接口,存取数据时要注意数据的大小。

  • 关于存储时数据的大小问题

    • AppStorage没有大小限制,单条数据[k,v)],v也没有限制,但是不建议单条v大于1kb,大于1kb建议使用数据库。多条使用没有限制,会动态分配的。

    • LocalStorage底层实现是一个map,理论上没有大小限制。

  • 参考链接:文档中心

2.LocalStorage,AppStorage,及PersistentStorage的具体实现及分别适用哪些场景

LocalStorage

LocalStorage是ArkTS为构建页面级别状态变量提供存储的内存内“数据库”。

  • 应用程序可以创建多个LocalStorage实例,LocalStorage实例可以在页面内共享,也可以通过GetShared接口,实现跨页面、UIAbility实例内共享。

  • 组件树的根节点,即被@Entry装饰的@Component,可以被分配一个LocalStorage实例,此组件的所有子组件实例将自动获得对该LocalStorage实例的访问权限。

  • 被@Component装饰的组件最多可以访问一个LocalStorage实例和AppStorage,未被@Entry装饰的组件不可被独立分配LocalStorage实例,只能接受父组件通过@Entry传递来的LocalStorage实例。一个LocalStorage实例在组件树上可以被分配给多个组件。

  • LocalStorage中的所有属性都是可变的。

应用程序决定LocalStorage对象的生命周期。当应用释放最后一个指向LocalStorage的引用时,比如销毁最后一个自定义组件,LocalStorage将被JS Engine垃圾回收。

LocalStorage根据与@Component装饰的组件的同步类型不同,提供了两个装饰器:

  • @LocalStorageProp:@LocalStorageProp装饰的变量和与LocalStorage中给定属性建立单向同步关系。

  • @LocalStorageLink:@LocalStorageLink装饰的变量和在@Component中创建与LocalStorage中给定属性建立双向同步关系。

使用场景:

  • 应用逻辑使用LocalStorage

    let para: Record<string,number> = { 'PropA': 47 };
    let storage: LocalStorage = new LocalStorage(para); // 创建新实例并使用给定对象初始化
    let propA: number | undefined = storage.get('PropA') // propA == 47
    let link1: SubscribedAbstractProperty<number> = storage.link('PropA'); // link1.get() == 47
    let link2: SubscribedAbstractProperty<number> = storage.link('PropA'); // link2.get() == 47
    let prop: SubscribedAbstractProperty<number> = storage.prop('PropA'); // prop.get() == 47
    link1.set(48); // two-way sync: link1.get() == link2.get() == prop.get() == 48
    prop.set(1); // one-way sync: prop.get() == 1; but link1.get() == link2.get() == 48
    link1.set(49); // two-way sync: link1.get() == link2.get() == prop.get() == 49

  • 从UI内部使用LocalStorage

    除了应用程序逻辑使用LocalStorage,还可以借助LocalStorage相关的两个装饰器@LocalStorageProp和@LocalStorageLink,在UI组件内部获取到LocalStorage实例中存储的状态变量。

AppStorage

AppStorage是在应用启动的时候会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。AppStorage将在应用运行过程保留其属性。属性通过唯一的键字符串值访问。

AppStorage可以和UI组件同步,且可以在应用业务逻辑中被访问。

AppStorage支持应用的主线程内多个UIAbility实例间的状态共享。

AppStorage中的属性可以被双向同步,数据可以是存在于本地或远程设备上,并具有不同的功能,比如数据持久化(详见PersistentStorage)。这些数据是通过业务逻辑中实现,与UI解耦,如果希望这些数据在UI中使用,需要用到@StorageProp和@StorageLink。

使用场景:

  • 从应用逻辑使用AppStorage

    AppStorage是单例,它的所有API都是静态的,使用方法类似于中LocalStorage对应的非静态方法。

    AppStorage.setOrCreate('PropA', 47);
    ​
    let storage: LocalStorage = new LocalStorage();
    storage.setOrCreate('PropA',17);
    let propA: number | undefined = AppStorage.get('PropA') // propA in AppStorage == 47, propA in LocalStorage == 17
    let link1: SubscribedAbstractProperty<number> = AppStorage.link('PropA'); // link1.get() == 47
    let link2: SubscribedAbstractProperty<number> = AppStorage.link('PropA'); // link2.get() == 47
    let prop: SubscribedAbstractProperty<number> = AppStorage.prop('PropA'); // prop.get() == 47
    ​
    link1.set(48); // two-way sync: link1.get() == link2.get() == prop.get() == 48
    prop.set(1); // one-way sync: prop.get() == 1; but link1.get() == link2.get() == 48
    link1.set(49); // two-way sync: link1.get() == link2.get() == prop.get() == 49
    ​
    storage.get<number>('PropA') // == 17
    storage.set('PropA', 101);
    storage.get<number>('PropA') // == 101
    ​
    AppStorage.get<number>('PropA') // == 49
    link1.get() // == 49
    link2.get() // == 49
    prop.get() // == 49

  • 从UI内部使用AppStorage和LocalStorage

    @StorageLink变量装饰器与AppStorage配合使用,正如@LocalStorageLink与LocalStorage配合使用一样。此装饰器使用AppStorage中的属性创建双向数据同步。

PersistentStorage

PersistentStorage将选定的AppStorage属性保留在设备磁盘上。应用程序通过API,以决定哪些AppStorage属性应借助PersistentStorage持久化。UI和业务逻辑不直接访问PersistentStorage中的属性,所有属性访问都是对AppStorage的访问,AppStorage中的更改会自动同步到PersistentStorage。

PersistentStorage和AppStorage中的属性建立双向同步。应用开发通常通过AppStorage访问PersistentStorage,另外还有一些接口可以用于管理持久化属性,但是业务逻辑始终是通过AppStorage获取和设置属性的

使用场景:

从AppStorage中访问PersistentStorage初始化的属性

在PersistentStorage之前访问AppStorage中的属性

在PersistentStorage之后访问AppStorage中的属性

  • 参考链接:文档中心

3.首选项异步存储在并发场景上的注意事项

首选项preference提供了异步存储接口,首选项的数据存储维度分为内存和沙盒,为避免内存过大导致报警,要控制首选项数据存储的数据,可以使用await来控制并发存储的问题。

4.数据存储怎么存?都用过什么数据存储?如appstorage、数据库等,这个会结合项目介绍问,可以在多看看其他存储方式及使用

  • 用户首选项实现数据持久化(Perferences)

    用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。当用户希望有一个全局唯一存储的地方,可以采用用户首选项来进行存储。Preferences会将该数据缓存在内存中,当用户读取的时候,能够快速从内存中获取数据,当需要持久化时可以使用flush接口将内存中的数据写入持久化文件中。Preferences会随着存放的数据量越多而导致应用占用的内存越大,因此,Preferences不适合存放过多的数据,适用的场景一般为应用保存用户的个性化设置(字体大小,是否开启夜间模式)等。

  • 键值型数据库实现数据持久化

    键值型数据库存储键值对形式的数据,当需要存储的数据没有复杂的关系模型,比如存储商品名称及对应价格、员工工号及今日是否已出勤等,由于数据复杂度低,更容易兼容不同数据库版本和设备类型,因此推荐使用键值型数据库持久化此类数据。

  • 关系型数据库实现数据持久化

    关系型数据库基于SQLite组件,适用于存储包含复杂关系数据的场景,比如一个班级的学生信息,需要包括姓名、学号、各科成绩等,又或者公司的雇员信息,需要包括姓名、工号、职位等,由于数据之间有较强的对应关系,复杂程度比键值型数据更高,此时需要使用关系型数据库来持久化保存数据。

  • AppStorage:应用全局的UI状态存储

    AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。

  • LocalStorage:页面级UI状态存储

    LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。

  • 参考链接:

    • 文档中心

    • 文档中心

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

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

相关文章

vruntime

vruntime vruntime 变量存放进程的虚拟运行时间,虚拟时间是以 ns 为单位的,which is the actual runtime (the amount of time spent running) normalized (or weighted) by the number of runnable processesvruntime 和定时器节拍不再相关。优先级相同的所有进程的虚拟运行时…

计算机网络学习实践:配置主机通过DHCP获取IP并通过域名访问web服务器

计算机网络学习实践&#xff1a;配置主机通过DHCP获取IP并通过域名访问web服务器 点一点就能配置&#xff0c;不需要输入命令 1.实验准备 实验环境&#xff1a;思科的模拟器 实验设备&#xff1a; 3个服务器&#xff0c;1个二层交换机&#xff08;不是三层的&#xff09;&a…

JavaScript第七讲:数组,及练习题

目录 今天话不多说直接进入正题&#xff01; 1. 创建数组对象 2. 数组长度 3. 遍历一个数组 4. 连接数组 5. 通过指定分隔符&#xff0c;返回一个数组的字符串表达 6. 分别在最后的位置插入数据和获取数据(获取后删除) 7. 分别在最开始的位置插入数据和获取数据(获取后删…

fatal error C1859:意外的预编译头错误,只需重新运行编译器就可能修复此问题

解决 菜单栏–生成–清理解决方案–菜单栏–生成–生成解决方案

对象业务的修改元数据接口

如下是官方文档中针对元数据的说明。 After you upload the object, you cannot modify object metadata. The only way to modify object metadata is to make a copy of the object and set the metadata. 对象的元数据仅在上传对象时或者复制对象时支持修改&#xff0c;在某…

一个弹出的虚假安全警告去除

虚假的安全警告 poratus.azurewebsites.net Pornographic spyware detected! Remove viruses with Avira Antivirus 通过 Microsoft Edge GPT-4 (OpenAI) 这个提示可能是一个虚假的安全警告&#xff0c;被称为“恐吓软件”&#xff08;scareware&#xff09;&#xff0c;旨在…

2024年上半年高级信息系统项目管理师考后总结

复习了大概两个月&#xff0c;终于度过了这场考试。又是加班996&#xff0c;又是复习听课写论文做真题&#xff0c;真心累。没办法&#xff0c;年纪大了&#xff0c;不考考证&#xff0c;没法混啊。 所以&#xff0c;建议大家趁年轻&#xff0c;必须必须必须把高级软考的证给拿…

名下企业查询,清晰明了;在线操作,方便快捷

在现代社会&#xff0c;越来越多的人开始涉足创业和投资&#xff0c;拥有自己的企业成为一种时尚。然而&#xff0c;随之而来的是繁琐的企业注册流程和复杂的信息查询。为了解决这个问题&#xff0c;挖数据平台推出了一项名下企业查询接口&#xff0c;提供了一种方便快捷的方式…

pytorch onnx ncnn间的关系

PyTorch、ONNX 和 NCNN 是深度学习领域中的三个重要工具或框架&#xff0c;它们在模型开发、转换和部署过程中扮演着不同但相互关联的角色。以下是它们之间的关系和各自的作用&#xff1a; PyTorch 角色 PyTorch 是一个开源的深度学习框架&#xff0c;由 Facebooks AI Resea…

计算机网络介绍

计算机网络介绍 概述网络概述相关硬件 链路层VLAN概念VLAN 特点VLAN 的划分帧格式端口类型原理 STP概念特点原理 Smart Link概念特点组网 网络层ARP概念原理 IP概念版本IP 地址 IPv4IP 地址数据报格式 IPv6特点IP 地址数据报格式 ICMP概念分类报文格式 VRRP概念原理报文格式 OS…

MySQL创建新用户并设置新密码

创建新用户并设置新密码的步骤在 MySQL 中相对直接。以下是具体步骤&#xff1a; 登录到 MySQL&#xff1a; 打开终端或命令行界面&#xff0c;使用以下命令以 root 用户或其他具有足够权限的用户登录到 MySQL 服务器&#xff1a; mysql -u root -p输入 root 用户的密码。 选择…

echarts中api返回数据的结构是时间和数据是两个数组返回的如何使用

如果ECharts的API返回的数据结构是时间和数据分别作为两个数组返回的&#xff0c;你可以将这两个数组分别赋值给x轴和y轴的数据。 例如&#xff0c;假设API返回了以下两个数组&#xff1a; const timeData [2022-01-01, 2022-01-02, 2022-01-03]; const valueData [10, 20,…

片上电控系统集成技术

一、背景 片上电机控制系统集成技术&#xff08;On-Chip Motor Control System Integration&#xff09;是一种先进的电子工程技术&#xff0c;它主要聚焦于将复杂的电机控制算法和硬件组件整合到单一集成电路&#xff08;IC&#xff09;中&#xff0c;以便于高效、精确地管理…

计算机毕业设计 | 基于Koa+vue的高校宿舍管理系统宿舍可视化系统

项目介绍 项目背景 随着科技的发展&#xff0c;智能化管理越来越重要。大学生在宿舍的时间超过了1/3&#xff0c;因此良好的宿舍管理对学生的生活和学习极为关键。学生宿舍管理系统能够合理安排新生分配宿舍&#xff0c;不浪费公共资源&#xff0c;减轻学校管理压力&#xff…

9.1JavaEE——Spring JDBC

一、JDBCTemplate概述 1、JDBCTemplate作用 针对数据库操作&#xff0c;Spring框架提供了JdbcTemplate类&#xff0c;JdbcTemplate是一个模板类&#xff0c;Spring JDBC中的更高层次的抽象类均在JdbcTemplate模板类的基础上创建。 JdbcTemplate类提供了操作数据库的基本方法&a…

计算机视觉与深度学习实战,Python工具,深度学习的视觉场景识别

一、引言 随着人工智能技术的快速发展,计算机视觉和深度学习已成为当今最热门的研究领域之一。在计算机视觉中,视觉场景识别是一项重要的任务,旨在通过计算机对图像或视频中的场景进行自动分类和理解。Python作为一种强大的编程语言,结合深度学习框架,为计算机视觉领域的研…

关于工作组

什么是局域网&#xff08;内网&#xff09; 我们常说的内网指的就是局域网&#xff0c;局域网&#xff08;Local Area Network&#xff0c;简称LAN&#xff09;是指在相对较小的地理范围内&#xff0c;如一个办公室、学校、住宅区或建筑群内部&#xff0c;通过通信设备&#xf…

STL的pair知识点大全

1&#xff1a;set容器set.equal range(elem) 1.上限是闭区间&#xff0c;下限是开区间&#xff0c;如[beg,end)返回容器中与elem相等的上下限的两个迭代器&#xff0c;pair中。函数返回两个迭代器&#xff0c;而这两个迭代器被封装在pair中。 pair< set<int>::iterat…

如何快速入门使用Vue.js

目录 学习步骤具体案例案例一&#xff1a;Todo List 应用案例二&#xff1a;用户管理系统 学习步骤 基础知识&#xff1a; HTML/CSS/JavaScript&#xff1a;掌握基本的网页结构、样式和交互是必须的。ES6&#xff1a;了解现代JavaScript的特性&#xff0c;如箭头函数、解构赋值…

vue3 diff源码梳理学习笔记

1、只比较同层 2、双端比较 3、判断流程 1、先判断是否是首次渲染&#xff1b; 2、vnode oldvnode 指向同一个对象&#xff1f; 3、oldvnode dom 关联到真实的元素上&#xff0c;依次更新dom上的属性&#xff0c;class style props events; 4、针对简单的文本节点 只需要更新…