• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# PersistenceV2: 持久化储存UI状态
2
3为了增强状态管理框架对持久化存储UI的能力,开发者可以使用PersistenceV2存储持久化的数据。AppStorageV2是运行时内存,但是在应用退出再次启动后,依然能保存选定的结果,是应用开发中十分常见的现象,这就需要用到PersistenceV2。
4
5PersistenceV2是应用程序中的可选单例对象。此对象的作用是持久化存储UI相关的数据,以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同。
6
7>**说明:**
8>
9>PersistenceV2从API version 12开始支持。
10>
11>当前状态管理(V2试用版)仍在逐步开发中,相关功能尚未成熟,建议开发者尝鲜试用。
12
13
14## 概述
15
16PersistenceV2是在应用UI启动时会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。数据通过唯一的键字符串值访问。不同于AppStorageV2,PersistenceV2还将最新数据储存在设备磁盘上(持久化)。这意味着,应用退出再次启动后,依然能保存选定的结果。
17
18对于与PersistenceV2关联的[\@ObservedV2](arkts-new-observedV2-and-trace.md)对象,该对象的[\@Trace](arkts-new-observedV2-and-trace.md)属性的变化,会触发**整个关联对象的自动持久化**;非[\@Trace](arkts-new-observedV2-and-trace.md)属性的变化则不会,如有必要,可调用PersistenceV2 API手动持久化。
19
20PersistenceV2可以和UI组件同步,且可以在应用业务逻辑中被访问。
21
22PersistenceV2支持应用的[主线程](../application-models/thread-model-stage.md)内多个UIAbility实例间的状态共享。
23
24
25## 使用说明
26
27### connect:创建或获取储存的数据
28
29```JavaScript
30static connect<T extends object>(
31    type: TypeConstructorWithArgs<T>,
32    keyOrDefaultCreator?: string | StorageDefaultCreator<T>,
33    defaultCreator?: StorageDefaultCreator<T>
34): T | undefined;
35```
36
37| connect      | 说明                                                  |
38| ------------ | ----------------------------------------------------- |
39| 参数         | type:指定的类型,若未指定key,则使用type的name作为key;</br > keyOrDefaultCreater:指定的key,或者是默认数据的构造器;</br > defaultCreator:默认数据的构造器。                                          |
40| 返回值       | 创建或获取数据成功时,返回数据;否则返回undefined。 |
41
42>**说明:**
43>
44>1、若未指定key,使用第二个参数作为默认构造器;否则使用第三个参数作为默认构造器(第二个参数非法也使用第三个参数作为默认构造器);
45>
46>2、确保数据已经存储在PersistenceV2中,可省略默认构造器,获取存储的数据;否则必须指定默认构造器,不指定将导致应用异常;
47>
48>3、同一个key,connect不同类型的数据会导致应用异常,应用需要确保类型匹配;
49>
50>4、key建议使用有意义的值,可由字母、数字、下划线组成,长度不超过255,使用非法字符或空字符的行为是未定义的;
51>
52>5、关联[\@Observed](arkts-observed-and-objectlink.md)对象时,由于该类型的name属性未定义,需要指定key或者自定义name属性。
53
54### remove:删除指定key的储存数据
55
56```JavaScript
57static remove<T>(keyOrType: string | TypeConstructorWithArgs<T>): void;
58```
59
60| remove       | 说明                                                  |
61| ------------ | ----------------------------------------------------- |
62| 参数         | keyOrType:需要删除的key;如果指定的是type类型,删除的key为type的name。                                          |
63| 返回值       | 无。 |
64
65>**说明:**
66>
67>删除PersistenceV2中不存在的key会报警告。
68
69### keys:返回所有PersistenceV2中的key
70
71```JavaScript
72static keys(): Array<string>;
73```
74
75| keys         | 说明                                                  |
76| ------------ | ----------------------------------------------------- |
77| 参数         | 无。                                         |
78| 返回值       | 所有PersistenceV2中的key。 |
79
80
81### save:手动持久化数据
82
83```JavaScript
84static save<T>(keyOrType: string | TypeConstructorWithArgs<T>): void;
85```
86
87| save         | 说明                                                  |
88| ------------ | ----------------------------------------------------- |
89| 参数         | keyOrType:需要手动持久化的key;如果指定的是type类型,key为type的name。                                          |
90| 返回值       | 无。 |
91
92>**说明:**
93>
94>由于非[\@Trace](arkts-new-observedV2-and-trace.md)的数据改变不会触发PersistenceV2的自动持久化,如有必要,可调用该接口持久化对应key的数据;
95>
96>手动持久化当前内存中不处于connect状态的key是无意义的。
97
98
99### notifyOnError:响应序列化或反序列化失败的回调
100
101```JavaScript
102static notifyOnError(callback: PersistenceErrorCallback | undefined): void;
103```
104
105| notifyOnError| 说明                                                  |
106| ------------ | ----------------------------------------------------- |
107| 参数         | callback:当序列化或者反序列化失败时,执行该回调;若传入undefined,取消该回调。|
108| 返回值       | 无。 |
109
110>**说明:**
111>
112>将数据存入磁盘时,需要对数据进行序列化;当某个key序列化失败时,错误是不可预知的;可调用该接口捕获异常。
113
114
115## 使用限制
116
1171、需要配合UI使用(UI线程),不能在其他线程使用,如不支持@Sendable;
118
1192、不支持collections.Setcollections.Map等类型;
120
1213、不支持非buildin类型,如PixelMap、NativePointer、ArrayList等Native类型;
122
1234、单个key支持数据大小约8k,过大会导致持久化失败;
124
1255、持久化的数据必须是class对象,不能是容器(如Array、Set、Map),不能是buildin的构造对象(如Date、Number);
126
1276、不支持循环引用的对象;
128
1297、只有[\@Trace](arkts-new-observedV2-and-trace.md)的数据改变会触发自动持久化,如V1状态变量、[\@Observed](arkts-observed-and-objectlink.md)对象、普通数据的改变不会触发持久化;
130
1318、不宜大量持久化数据,可能会导致页面卡顿。
132
133## 使用场景
134
135### 在两个页面之间存储数据
136
137页面1
138```ts
139import { router, PersistenceV2 } from '@kit.ArkUI';
140import { Sample } from '../Sample';
141
142// 接受序列化失败的回调
143PersistenceV2.notifyOnError((key: string, reason: string, msg: string) => {
144  console.error(`error key: ${key}, reason: ${reason}, message: ${msg}`);
145});
146
147@Entry
148@ComponentV2
149struct Page1 {
150  // 在PersistenceV2中创建一个key为Sample的键值对(如果存在,则返回PersistenceV2中的数据),并且和prop关联
151  // 对于需要换connect对象的prop属性,需要加@Local修饰(不建议对属性换connect的对象)
152  @Local prop: Sample = PersistenceV2.connect(Sample, () => new Sample())!;
153
154  build() {
155    Column() {
156      Button('Go to page2')
157        .onClick(() => {
158          router.pushUrl({
159            url: 'pages/Page2'
160          })
161        })
162
163      Button('Page1 connect the key Sample')
164        .onClick(() => {
165          // 在PersistenceV2中创建一个key为Sample的键值对(如果存在,则返回PersistenceV2中的数据),并且和prop关联
166          // 不建议对prop属性换connect的对象
167          this.prop = PersistenceV2.connect(Sample, 'Sample', () => new Sample())!;
168        })
169
170      Button('Page1 remove the key Sample')
171        .onClick(() => {
172          // 从PersistenceV2中删除后,prop将不会再与key为Sample的值关联
173          PersistenceV2.remove(Sample);
174        })
175
176      Button('Page1 save the key Sample')
177        .onClick(() => {
178          // 如果处于connect状态,持久化key为Sample的键值对
179          PersistenceV2.save(Sample);
180        })
181
182      Text(`Page1 add 1 to prop.p1: ${this.prop.f.p1}`)
183        .fontSize(30)
184        .onClick(() => {
185          this.prop.f.p1++;
186        })
187
188      Text(`Page1 add 1 to prop.p2: ${this.prop.f.p2}`)
189        .fontSize(30)
190        .onClick(() => {
191          // 页面不刷新,但是p2的值改变了
192          this.prop.f.p2++;
193        })
194
195      // 获取当前PersistenceV2里面的所有key
196      Text(`all keys in PersistenceV2: ${PersistenceV2.keys()}`)
197        .fontSize(30)
198    }
199  }
200}
201```
202
203页面2
204```ts
205import { PersistenceV2 } from '@kit.ArkUI';
206import { Sample } from '../Sample';
207
208@Entry
209@ComponentV2
210struct Page2 {
211  // 在PersistenceV2中创建一个key为Sample的键值对(如果存在,则返回PersistenceV2中的数据),并且和prop关联
212  // 对于需要换connect对象的prop属性,需要加@Local修饰(不建议对属性换connect的对象)
213  @Local prop: Sample = PersistenceV2.connect(Sample, () => new Sample())!;
214
215  build() {
216    Column() {
217      Button('Page2 connect the key Sample1')
218        .onClick(() => {
219          // 在PersistenceV2中创建一个key为Sample1的键值对(如果存在,则返回PersistenceV2中的数据),并且和prop关联
220          // 不建议对prop属性换connect的对象
221          this.prop = PersistenceV2.connect(Sample, 'Sample1', () => new Sample())!;
222        })
223
224      Text(`Page2 add 1 to prop.p1: ${this.prop.f.p1}`)
225        .fontSize(30)
226        .onClick(() => {
227          this.prop.f.p1++;
228        })
229
230      Text(`Page2 add 1 to prop.p2: ${this.prop.f.p2}`)
231        .fontSize(30)
232        .onClick(() => {
233          // 页面不刷新,但是p2的值改变了;只有重新初始化才会改变
234          this.prop.f.p2++;
235        })
236
237      // 获取当前PersistenceV2里面的所有key
238      Text(`all keys in PersistenceV2: ${PersistenceV2.keys()}`)
239        .fontSize(30)
240    }
241  }
242}
243```
244
245数据页面
246```ts
247import { Type } from '@kit.ArkUI';
248
249// 数据中心
250@ObservedV2
251class SampleChild {
252  @Trace p1: number = 0;
253  p2: number = 10;
254}
255
256@ObservedV2
257export class Sample {
258  // 对于复杂对象需要@Type修饰,确保序列化成功
259  @Type(SampleChild)
260  @Trace f: SampleChild = new SampleChild();
261}
262```
263
264