# 14.10:AppStageV2

AppStageV2 是 ArkUI 开发框架提供的全局 UI 状态存储中心,它是一个内存及的全局单例对象并在应用 UI 启动时被创建,开发者可以使用 AppStorageV2 存储应用内的全局状态数据。本节笔者简单介绍一下 AppStorageV2 的使用。

# 14.10.1:约束与限制

  • AppStorageV2 关联的 key 必须保证同类型,否则应用异常。
  • AppStorageV2 关联的 key 长度不超过 255,禁止非法字符。
  • AppStorageV2 只能在 UI 线程内使用,不支持 @Sendable
  • AppStorageV2 属于应用级数据仓库,支持跨组件、跨页面跨Ability数据共享。

# 14.10.2:语法介绍

AppStorageV2 提供了应用级的全局共享的能力,它的定义如下:

export declare class AppStorageV2 {
    // 查询数据
    static connect<T extends object>(type: TypeConstructorWithArgs<T>, keyOrDefaultCreator?: string | StorageDefaultCreator<T>, defaultCreator?: StorageDefaultCreator<T>): T | undefined;
    // 删除数据
    static remove<T>(keyOrType: string | TypeConstructorWithArgs<T>): void;
    // 返回所有key
    static keys(): Array<string>;
}
1
2
3
4
5
6
7
8
  • connect(): 创建或获取储存的数据,参数说明如下:
    • type: 指定的类型,若未指定 key,则使用type的name作为key;
    • keyOrDefaultCreater: 指定的key,或者是默认数据的构造器;
    • defaultCreator: 默认数据的构造器。
  • remove(): 删除指定 key 的储存数据,参数说如下:
    • keyOrType: 需要删除的 key;如果指定的是 type 类型,删除的 keytypename
  • keys(): 返回所有 AppStorageV2 中的 key

connect() 方法的使用格式如下:

@Entry
@ComponentV2
struct Index {

  // key为User
  private user1: User = AppStorageV2.connect(User, () => new User("张三", ""))!
  // key为global_user
  private user2: User = AppStorageV2.connect(User, "global_user", () => new User("李四", ""))!

  build() { }
}
1
2
3
4
5
6
7
8
9
10
11

user1 绑定了 AppStorageV2key 为默认值 User 的对象,首次访问时创建一个 User 实例并与之绑定,user2 绑定了 AppStorageV2keyglobal_user 的对象,首次访问时创建一个 User 实例并与之绑定。

📢:user1user2 因为绑定的的 key 不一致导致他们属于不同的实例,如果要求一直,key 必须保证一致。

# 14.10.3:简单样例

AppStorageV2 的简单实用如下所示:

import { AppStorageV2 } from '@kit.ArkUI';

@ObservedV2
class User {
  @Trace
  userName: string = "张三"
  @Trace
  birthday: string = "2020-4-12"
}


@Entry @ComponentV2 struct Page_state {

  // key为User
  private user: User = AppStorageV2.connect(User, () => new User())!;

  build() {
    Column({space: 20}) {
      Text("用户:" + this.user.userName + ", 生日:" + this.user.birthday)

      Button("更改姓名")
        .onClick(() => {
          this.user.userName = "李四:" + new Date().getMilliseconds().toString()
        })

      CustomWidget()
    }
    .width("100%")
  }

}

@ComponentV2 struct CustomWidget {

  // key为User
  @Local updateBirthday: User = AppStorageV2.connect(User, () => new User())!;

  build() {
    Column({space: 20}) {
      Text("用户:" + this.updateBirthday.userName + ", 生日:" + this.updateBirthday.birthday)
      Button("更改生日")
        .onClick(() => {
          this.updateBirthday.birthday = new Date().getMilliseconds().toString()
        })
    }
    .width("100%")

  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

样例运行结果如下图所示:

14_10_3_1

由样例可知,组件 Page_stateCustomWidget 内的 user 实例都和 AppStorageV2 做了绑定,首次访问 AppStorageV2 时会调用回调方法生成一个 User 对象缓存并返给调用者,后续对与该 User 的修改都会触发所有与 AppStorageV2 绑定的 User 并触发 UI 刷新。

# 14.10.4:磁盘持久化

AppStorageV2 属于内存级数据存储中心,当杀掉 App 后再重新打开,其保存的数据不复存在,如果需要把数据缓存在磁盘上实现持久化,可以利用 @Monitor 装饰器观察 User 的变化,如果变化则把User信息持久化,然后在 AppStorageV2 内返回持久化的User信息即可。简单样例如下所示:

import { AppStorageV2 } from '@kit.ArkUI';
import { KVManager } from '../utils/KVManager';
import { JSON } from '@kit.ArkTS';

const MONITOR_PREFIX = "__ob_"
const USER_KEY = "user_key_global"

@ObservedV2
class User {
  @Trace
  userName: string = "张三"
  @Trace
  birthday: string = "2020-4-12"

  // 监听属性值的变化做本地持久化操作
  @Monitor("userName", "birthday") notifyAttributeChanged(monitor: IMonitor) {
    let value = JSON.stringify(this).replaceAll(MONITOR_PREFIX, "")
    console.log("user info: " + value)
    KVManager.get().put(USER_KEY, value)
  }

  // 从本地磁盘取出缓存数据
  static create(): User {
    let value = KVManager.get().get(USER_KEY, "") as string
    if (value.length < 1) {
      return new User()
    }
    let object = JSON.parse(value) as User
    let user = new User();
    user.userName = object.userName
    user.birthday = object.birthday
    return user
  }

}


@Entry @ComponentV2 struct Page_state {

  // key为User,返回值调用了User的create()方法从本地缓存中读取数据
  private user: User = AppStorageV2.connect(User, () => User.create())!;

  build() {
    Column({space: 20}) {
      Text("用户:" + this.user.userName + ", 生日:" + this.user.birthday)

      Button("更改姓名")
        .onClick(() => {
          this.user.userName = "李四:" + new Date().getMilliseconds().toString()
        })

      CustomWidget()
    }
    .width("100%")
  }

}

@ComponentV2 struct CustomWidget {

  // key为User,返回值调用了User的create()方法从本地缓存中读取数据
  @Local updateBirthday: User = AppStorageV2.connect(User, () => User.create())!;

  build() {
    Column({space: 20}) {
      Text("用户:" + this.updateBirthday.userName + ", 生日:" + this.updateBirthday.birthday)
      Button("更改生日")
        .onClick(() => {
          this.updateBirthday.birthday = new Date().getMilliseconds().toString()
        })
    }
    .width("100%")

  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

样例运行结果如下图所示:

14_10_4_1

上述做法实现了内存数据本地持久化,但是这样实现有一个弊端,当项目里使用了众多 Model 时,代码就会重复起来,为了解决这种问题,ArkUI 开发框架提供了 @PersistenceV2 装饰器来实现数据持久化能力,下节笔者将简单介绍一下 @PersistenceV2 的使用。

请作者喝杯咖啡

津公网安备 12011402001367号

津ICP备2020008934号-2

中央网信办互联网违法和不良信息举报中心

天津市互联网违法和不良信息举报中心