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

typescript 复制代码
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

typescript 复制代码
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')

示例代码:

typescript 复制代码
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

示例代码

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

PersistenceV2

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

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

typescript 复制代码
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。
返回值 无。

示例代码

typescript 复制代码
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,取消该回调。
返回值 无。

示例代码

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

序列化的补充

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

typescript 复制代码
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 ,因为是直接读写磁盘,所以不适合持久化大量数据,会导致应用性能下下降。
相关推荐
蓝枫amy2 小时前
HarmonyOS快速入门
华为·harmonyos
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062065 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb5 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角5 小时前
CSS 颜色
前端·css
浪浪山小白兔6 小时前
HTML5 新表单属性详解
前端·html·html5
程序猿阿伟7 小时前
《探秘鸿蒙Next:如何保障AI模型轻量化后多设备协同功能一致》
人工智能·华为·harmonyos
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579657 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
程序猿阿伟7 小时前
《探秘鸿蒙Next:人工智能助力元宇宙高效渲染新征程》
人工智能·华为·harmonyos