Harmony状态管理AppStorageV2和PersistenceV2

简介: Harmony状态管理AppStorageV2和PersistenceV2

Harmony状态管理AppStorageV2和PersistenceV2

前言

HarmonyOS应用开发过程中,我们已经学习过了不少关于状态管理相关的技术,如

  • @ObservedV2装饰器和@Trace装饰器:类属性变化观测
  • @ComponentV2装饰器:自定义组件
  • @Local装饰器:组件内部状态
  • @Param:组件外部输入
  • @Once:初始化同步一次
  • @Event装饰器:组件输出
  • @Monitor装饰器:状态变量修改监听
  • @Provider装饰器和@Consumer装饰器:跨组件层级双向同步(没有讲过)
  • @Computed装饰器:计算属性
  • @Type装饰器:标记类属性的类型

以上状态管理技术,都是围绕着组件内部本身的。现在要讲解的AppStorageV2PersistenceV2可以理解为应用/全局的状态管理技术。

  1. AppStorageV2是应用级别的数据管理技术,跨组件、跨页面。只要是主线程之内的UIAbility实例都可以共享数据。但是退出应用数
    据会自动销毁。
  2. PersistenceV2是应用级别的数据持久化技术,数据是直接存在设备磁盘上的,退出重新进入后,数据还存在

AppStorageV2

实际开发中,我们避免不了需要将数据实时共享在多个页面或者组件中,如个人信息,那么便可以考虑将数据存放在AppStorageV2中。

AppStorageV2是应用级别的数据管理技术,跨组件、跨页面。只要是主线程之内的UIAbility实例都可以共享数据。但是退出应用数据会自动

销毁。

AppStorageV2核心API

名称 作用
connect 创建或获取储存的数据
remove 删除指定key的储存数据
keys 返回所有AppStorageV2中的key

connect

创建或获取储存的数据

connect 说明
参数 type:指定的类型,若未指定key,则使用type的name作为key;
keyOrDefaultCreater:指定的key,或者是默认数据的构造器;
defaultCreator:默认数据的构造器。
返回值 创建或获取数据成功时,返回数据;否则返回undefined。

示例代码:

Index.ets

import { AppStorageV2, router } from '@kit.ArkUI'
@ObservedV2
export class Person {
  @Trace
  age: number = 10
}
@Entry
@ComponentV2
struct Index {
  @Local person: Person = AppStorageV2.connect(Person, () => new Person)!
  build() {
    Column() {
      Text("A页面")
      // 预览器会失效
      Button(`年龄:${this.person.age}`)
        .onClick(() => {
          this.person.age++
        })
      Button("跳转到B页面")
        .onClick(() => {
          router.pushUrl({
            url: "pages/Index2"
          })
        })
    }
  }
}

代码解释

@Local person: Person = AppStorageV2.connect(Person, () => new Person)! 创建或者读取 keyPerson的数据。

@Local 是用来修饰person,表示person是一个状态,状态改变时,会引起UI的更新

.connect(Person,.. Person,作为connect方法的第一个参数,表示 Person类型

.connect(Person, () => new Person)!,由于connect中没有传入特定的key,那么便将Person.name视作key 。相当于

.connect(Person, Person.name,() => new Person)! 或者

.connect(Person,'Person',() => new Person)!

同时,因为有 () => new Person的作用,那么初始的数据也有了。

最后,因为 connect的返回值可能为空,因此在最后加上一个 表示非空断言

值得注意的是,以上代码在预览器上显示时,会得出 age = undefined的结果,所以需要在模拟器上测试

最后,如果你在A页面使用以上代码,修改了 age,那么B页面上也使用了age。那么便可以看到两个页面的数据是一样的。

Index.ets

import { Person } from "./Index";
import { AppStorageV2 } from '@kit.ArkUI';
@Entry
@ComponentV2
struct Index2 {
  @Local person: Person = AppStorageV2.connect(Person, () => new Person)!
  build() {
    Column() {
      Text("B页面")
      Button(`age:${this.person.age}`)
    }
  }
}

结果

remove

删除指定key的储存数据

remove 说明
参数 keyOrType:需要删除的key;如果指定的是type类型,删除的key为type的name。
返回值 无。

比如:AppStorageV2.remove(Person) 其实是等价于

AppStorageV2.remove(Person.name) 或者 AppStorageV2.remove('Person')

示例代码:

import { AppStorageV2, router } from '@kit.ArkUI'
@ObservedV2
export class Person {
  @Trace
  age: number = 10
}
@Entry
@ComponentV2
struct Index {
  @Local person: Person = AppStorageV2.connect(Person, () => new Person)!
  build() {
    Column({ space: 10 }) {
      Text("A页面")
      // 预览器会失效
      Button(`年龄:${this.person.age}`)
        .onClick(() => {
          this.person.age++
        })
      Button("跳转到B页面")
        .onClick(() => {
          router.pushUrl({
            url: "pages/Index2"
          })
        })
      Button("删除数据啦")
        .onClick(() => {
          AppStorageV2.remove(Person)
        })
    }
  }
}

如果此时执行了 remove方法,那么此时无论A页面中如何修改 person数据,AppStorageV2 中都不会跟随相应。B页面的perosn数据都不会受到影响。

keys

返回所有AppStorageV2中的key

示例代码

Button("返回AppStorageV2所有的keys")
    .onClick(() => {
      console.log("AppStorageV2.keys()", AppStorageV2.keys())
    })

PersistenceV2

PersistenceV2是应用级别的数据持久化技术,数据是直接存在设备磁盘上的,退出重新进入后,数据还存在

PersistenceV2核心API和AppStorageV2类似,都提供了 connectremovekeys

import { PersistenceV2 } from '@kit.ArkUI'
@ObservedV2
export class Person {
  @Trace
  age: number = 10
}
@Entry
@ComponentV2
struct Index {
  @Local person: Person = PersistenceV2.connect(Person, () => new Person)!
  build() {
    Column({ space: 10 }) {
      Text("A页面")
      // 预览器会失效
      Button(`年龄:${this.person.age}`)
        .onClick(() => {
          this.person.age++
        })
    }
  }
}

    
            
    
  

此时打开设备的文件目录,可以看到是实实在在把数据写到了磁盘中的。

/data/app/el2/100/base/com.example.你的包名/haps/entry/files/persistent_storage

需要注意的是,PersistenceV2还有另外的两个API

  1. save 由于非@Trace的数据改变不会触发PersistenceV2的自动持久化,因此可以手动的调用save 进行持久化
  2. notifyOnError 表示响应序列化或反序列化失败的回调 可以做错误处理

save

手动对@Trace的数据进行持久化

save 说明
参数 keyOrType:需要手动持久化的key;如果指定的是type类型,key为type的name。
返回值 无。

示例代码

import { PersistenceV2 } from '@kit.ArkUI'
export class Person {
  age: number = 10
}
@Entry
@ComponentV2
struct Index {
  @Local person: Person = PersistenceV2.connect(Person, () => new Person)!
  build() {
    Column({ space: 10 }) {
      Text("A页面")
      // 预览器会失效
      Button(`年龄:${this.person.age}`)
        .onClick(() => {
          this.person.age++
          console.log("this.person.age", this.person.age)
          PersistenceV2.save(Person)
        })
    }
  }
}


  1. 首次打开页面,直接修改数据,此时发现UI不会刷新,但是 日志输出却显示 age再增加(因为没有了@ObservedV2和@Trace监听)
  2. 此时退出应用,重新打开,却发现age会变成上一次增加后的数据。因为每次修改后,都调用了save方法。已经把数据持久化到磁盘中了。当重新打开页面时,会重新执行 @Local person: Person = PersistenceV2.connect(Person, () => new Person)!
    代码,便从磁盘中读取出数据渲染到UI上

notifyOnError

表示响应序列化或反序列化失败的回调 可以做错误处理

notifyOnError 说明
参数 callback:当序列化或者反序列化失败时,执行该回调;若传入undefined,取消该回调。
返回值 无。

示例代码

// 接受序列化失败的回调
PersistenceV2.notifyOnError((key: string, reason: string, msg: string) => {
  console.error(`error key: ${key}, reason: ${reason}, message: ${msg}`);
});

序列化的补充

如果要存储的数据是复杂类型嵌套的数据,需要使用 @Type 防止数据丢失

import { PersistenceV2, Type } from '@kit.ArkUI'
class Son {
  weight: number = 100
}
export class Person {
  age: number = 10
  // 嵌套复杂类型,为了防止序列化数据失败,需要使用 @Type标记类型
  @Type(Son)
  son: Son = new Son()
}

小结

  1. 如果考虑需要全局共享数据,那么可以考虑使用 AppStorageV2
  2. 如果考虑数据需要持久化,那么可以使用 PersistenceV2 ,因为是直接读写磁盘,所以不适合持久化大量数据,会导致应用性能下下降。
目录
相关文章
|
应用服务中间件 nginx Docker
使用nginx进行http以及socket端口转发(快速提高docker开发效率)
本文介绍如何使用nginx进行http以及socket端口转发以快速提高docker开发效率
|
存储 人工智能 算法
聚类的k值确定之轮廓系数
聚类的k值确定之轮廓系数
4810 0
|
5月前
|
人工智能 弹性计算 云计算
阿里云学生专属算力包正式商业化:学习/AI创作/毕设/游戏一个包全搞定
2026年阿里云学生算力包包正式商业化,含学生专属优惠券及300元无门槛抵扣金。该算力包专为学生定制,提供多款云服务器规格及多个地域选择,每月享免费流量。活动强调动手实操,支持学习、AI创作等多场景,无需代码,一键启用。此外,阿里云与多所高校深度合作,推动云计算与AI技术在教育领域的应用。以下是学生算礼包的详细介绍。
1010 3
|
API 开发者
鸿蒙NEXT-API19获取上下文,在class中和ability中获取上下文,API迁移示例-解决无法在EntryAbility中无法使用最新版API获取上下文
本文介绍了鸿蒙API 16升级后,如何通过UIContext获取上下文及替代已废弃API的方法,包括组件、类和Ability中的使用示例,并提供了promptAction、router等常用API的迁移方案,帮助开发者顺利适配新版系统。
889 0
|
运维 网络协议 Linux
网络故障排除的7个关键维度
网络故障排除是确保网络稳定运行的关键,能减少停机时间、提升服务质量。本文介绍7个排查步骤:1. 检查硬件连接;2. 使用ipconfig检查IP配置;3. 进行DNS检查;4. 验证网络配置;5. 用其他设备测试;6. 检查IP冲突;7. 测试网络带宽和延迟。通过这些方法,可快速定位并解决问题,保障网络顺畅运行。
2775 5
ly~
|
传感器 存储 供应链
大数据在供应链管理中的具体应用案例
以下是大数据在供应链管理中的具体应用案例:沃尔玛通过整合内外部数据进行需求预测,提前调配应急物资;亚马逊利用大数据优化库存管理,提高周转率并降低成本;DHL通过传感器收集数据优化物流路线,提升运输效率。大数据的优势在于提高需求预测准确性、优化库存管理、提升物流效率、增强供应商管理和提高供应链可视性,从而实现全方位的供应链优化。
ly~
3745 2
|
索引
|
Java
线程池中线程抛了异常,该如何处理?
【8月更文挑战第27天】在Java多线程编程中,线程池(ThreadPool)是一种常用的并发处理工具,它能够有效地管理线程的生命周期,提高资源利用率,并简化并发编程的复杂性。然而,当线程池中的线程在执行任务时抛出异常,如果不妥善处理,这些异常可能会导致程序出现未预料的行为,甚至崩溃。因此,了解并掌握线程池异常处理机制至关重要。
1296 0
|
传感器 监控 供应链
介绍LoRA技术
介绍LoRA技术
928 2
|
调度 UED 开发者
【鸿蒙软件开发】UIAbility组件概况、生命周期与启动模式
【鸿蒙软件开发】UIAbility组件概况、生命周期与启动模式
1872 0
【鸿蒙软件开发】UIAbility组件概况、生命周期与启动模式