• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# PersistentStorage: Application State Persistence
2
3
4During application development, you may want selected attributes to persist even when the application is closed. In this case, you'll need PersistentStorage.
5
6
7PersistentStorage is an optional singleton object within an application. Its purpose is to persist selected AppStorage attributes so that their values are the same upon application re-start as they were when the application was closed.
8
9
10## Overview
11
12PersistentStorage retains the selected AppStorage attributes on the device. The application uses the API to determine which AppStorage attributes should be persisted with PersistentStorage. The UI and business logic do not directly access attributes in PersistentStorage. All attribute access is to AppStorage. Changes in AppStorage are automatically synchronized to PersistentStorage.
13
14PersistentStorage creates a two-way synchronization with attributes in AppStorage. A frequently used API function is to access AppStorage through PersistentStorage. Additional API functions include managing persisted attributes. The business logic always obtains or sets attributes through AppStorage.
15
16## Constraints
17
18PersistentStorage accepts the following types and values:
19
20- Primitive types such as number, string, boolean, and enum.
21- Objects that can be reconstructed by **JSON.stringify()** and **JSON.parse()**. In other words, built-in types such as Date, Map, and Set, as well as object attribute methods, are not supported.
22
23PersistentStorage does not accept the following types and values:
24
25- Nested objects (object arrays and object attributes), because the framework cannot detect the value changes of nested objects (including arrays) in AppStorage.
26- **undefined** and **null**.
27
28Data persistence is an operation that takes time. Applications should avoid the following situations:
29
30- Persistence of large data sets
31
32- Persistence of variables that change frequently
33
34It is recommended that the persistent variables of PersistentStorage be less than 2 KB. As PersistentStorage flushes data synchronously, a large amount of persistent data may result in time-consuming local data read and write operations in the UI thread, affecting UI rendering performance. If you need to store a large amount of data, consider using the database API.
35
36PersistentStorage can be called to persist data only when the [UIContext](../reference/apis-arkui/js-apis-arkui-UIContext.md#uicontext), which can be obtained through [runScopedTask](../reference/apis-arkui/js-apis-arkui-UIContext.md#runscopedtask), is specified.
37
38## Application Scenarios
39
40
41### Accessing PersistentStorage Initialized Attribute from AppStorage
42
431. Initialize the PersistentStorage instance.
44
45   ```ts
46   PersistentStorage.persistProp('aProp', 47);
47   ```
48
492. Obtain the corresponding attribute from AppStorage.
50
51   ```ts
52   AppStorage.get<number>('aProp'); // returns 47
53   ```
54
55   Alternatively, apply local definition within the component:
56
57
58   ```ts
59   @StorageLink('aProp') aProp: number = 48;
60   ```
61
62The complete code is as follows:
63
64
65```ts
66PersistentStorage.persistProp('aProp', 47);
67
68@Entry
69@Component
70struct Index {
71  @State message: string = 'Hello World'
72  @StorageLink('aProp') aProp: number = 48
73
74  build() {
75    Row() {
76      Column() {
77        Text(this.message)
78        // The current result is saved when the application exits. After the restart, the last saved result is displayed.
79        Text(`${this.aProp}`)
80          .onClick(() => {
81            this.aProp += 1;
82          })
83      }
84    }
85  }
86}
87```
88
89- First running after fresh application installation:
90  1. **persistProp** is called to initialize PersistentStorage. A search for the **aProp** attribute in PersistentStorage returns no result, because the application has just been installed.
91  2. A search for the attribute **aProp** in AppStorage still returns no result.
92  3. Create the **aProp** attribute of the number type in AppStorge and initialize it with the value 47.
93  4. PersistentStorage writes the **aProp** attribute and its value **47** to the local device. The value of **aProp** in AppStorage and its subsequent changes are persisted.
94  5. In the **\<Index>** component, create the state variable **\@StorageLink('aProp') aProp**, which creates a two-way synchronization with the **aProp** attribute in AppStorage. During the creation, the search in AppStorage for the **aProp** attribute is successful, and therefore, the state variable is initialized with the value **47** found in AppStorage.
95
96  **Figure 1** PersistProp initialization process
97
98![en-us_image_0000001553348833](figures/en-us_image_0000001553348833.png)
99
100- After a click event is triggered:
101  1. The state variable **\@StorageLink('aProp') aProp** is updated, triggering the **\<Text>** component to be re-rendered.
102  2. The two-way synchronization between the \@StorageLink decorated variable and AppStorage results in the change of the **\@StorageLink('aProp') aProp** being synchronized back to AppStorage.
103  3. The change of the **aProp** attribute in AppStorage triggers any other one-way or two-way bound variables to be updated. (In this example, there are no such other variables.)
104  4. Because the attribute corresponding to **aProp** has been persisted, the change of the **aProp** attribute in AppStorage triggers PersistentStorage to write the attribute and its new value to the device.
105
106- Subsequent application running:
107  1. **PersistentStorage.persistProp('aProp', 47)** is called. A search for the **aProp** attribute in PersistentStorage succeeds.
108  2. The attribute is added to AppStorage with the value found in PersistentStorage.
109  3. In the **\<Index>** component, the value of the @StorageLink decorated **aProp** attribute is the value written by PersistentStorage to AppStorage, that is, the value stored when the application was closed last time.
110
111
112### Accessing an Attribute in AppStorage Before PersistentStorage
113
114This example is an incorrect use. It is incorrect to use the API to access the attributes in AppStorage before calling **PersistentStorage.persistProp** or **persistProps**, because such a call sequence will result in loss of the attribute values used in the previous application run:
115
116
117```ts
118let aProp = AppStorage.setOrCreate('aProp', 47);
119PersistentStorage.persistProp('aProp', 48);
120```
121
122**AppStorage.setOrCreate('aProp', 47)**: The **aProp** attribute of the number type is created in AppStorage, and its value is set to the specified default value **47**. **aProp** is a persisted attribute. Therefore, it is written back to PersistentStorage, and the value stored in PersistentStorage from the previous run is lost.
123
124PersistentStorage.persistProp('aProp', 48): An attribute with the name **aProp** and value **47** – set through the API in AppStorage – is found in PersistentStorage.
125
126### Accessing an Attribute in AppStorage After PersistentStorage
127
128If you do not want to overwrite the values saved in PersistentStorage during the previous application run, make sure any access to attributes in AppStorage is made after a call to a PersistentStorage API.
129
130```ts
131PersistentStorage.persistProp('aProp', 48);
132if (AppStorage.get('aProp') > 50) {
133    // If the value stored in PersistentStorage exceeds 50, set the value to 47.
134    AppStorage.setOrCreate('aProp',47);
135}
136```
137
138After reading the data stored in PersistentStorage, the sample code checks whether the value of **aProp** is greater than 50 and, if it is, sets **aProp** to **47** through an API in AppStorage.
139