写点什么

HarmonyOS Next V2 状态管理 AppStorageV2 和 PersistenceV2

作者:万少
  • 2024-12-15
    江苏
  • 本文字数:3241 字

    阅读完需:约 11 分钟

HarmonyOS Next V2 状态管理 AppStorageV2 和 PersistenceV2

HarmonyOS Next V2 状态管理 AppStorageV2 和 PersistenceV2

前言

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


  • @ObservedV2装饰器和@Trace装饰器:类属性变化观测

  • @ComponentV2装饰器:自定义组件

  • @Local装饰器:组件内部状态

  • @Param:组件外部输入

  • @Once:初始化同步一次

  • @Event装饰器:组件输出

  • @Monitor装饰器:状态变量修改监听

  • @Provider装饰器和@Consumer装饰器:跨组件层级双向同步(没有讲过)

  • @Computed装饰器:计算属性

  • @Type装饰器:标记类属性的类型


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


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

  2. 据会自动销毁。

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

AppStorageV2

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


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


销毁。


AppStorageV2 核心 API

connect

创建或获取储存的数据



示例代码:


Index.ets


import { AppStorageV2, router } from '@kit.ArkUI'

@ObservedV2export class Person { @Trace age: number = 10}


@Entry@ComponentV2struct 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@ComponentV2struct Index2 { @Local person: Person = AppStorageV2.connect(Person, () => new Person)!
build() { Column() { Text("B页面") Button(`age:${this.person.age}`) } }}
复制代码


结果


remove

删除指定 key 的储存数据



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


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


示例代码:


import { AppStorageV2, router } from '@kit.ArkUI'

@ObservedV2export class Person { @Trace age: number = 10}

@Entry@ComponentV2struct 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'

@ObservedV2export class Person { @Trace age: number = 10}@Entry@ComponentV2struct 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 的数据进行持久化



示例代码


import { PersistenceV2 } from '@kit.ArkUI'
export class Person { age: number = 10}
@Entry@ComponentV2struct 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)!

  3. 代码,便从磁盘中读取出数据渲染到 UI 上

notifyOnError

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



示例代码


// 接受序列化失败的回调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 ,因为是直接读写磁盘,所以不适合持久化大量数据,会导致应用性能下下降。


发布于: 刚刚阅读数: 6
用户头像

万少

关注

还未添加个人签名 2021-12-02 加入

还未添加个人简介

评论

发布
暂无评论
HarmonyOS Next V2 状态管理 AppStorageV2 和 PersistenceV2_鸿蒙_万少_InfoQ写作社区