# 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>;
}
2
3
4
5
6
7
8
- connect(): 创建或获取储存的数据,参数说明如下:
- type: 指定的类型,若未指定
key
,则使用type的name作为key; - keyOrDefaultCreater: 指定的key,或者是默认数据的构造器;
- defaultCreator: 默认数据的构造器。
- type: 指定的类型,若未指定
- remove(): 删除指定
key
的储存数据,参数说如下:- keyOrType: 需要删除的
key
;如果指定的是type
类型,删除的key
为type
的name
。
- keyOrType: 需要删除的
- 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() { }
}
2
3
4
5
6
7
8
9
10
11
user1
绑定了 AppStorageV2 内 key
为默认值 User
的对象,首次访问时创建一个 User
实例并与之绑定,user2
绑定了 AppStorageV2 内 key
为 global_user
的对象,首次访问时创建一个 User
实例并与之绑定。
📢:user1
和 user2
因为绑定的的 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%")
}
}
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
样例运行结果如下图所示:

由样例可知,组件 Page_state
和 CustomWidget
内的 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%")
}
}
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
样例运行结果如下图所示:

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