• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# @ohos.arkui.StateManagement (State Management)
2
3The state management module provides data storage, persistent data management, UIAbility data storage, and environment state and tools required by applications.
4
5>**NOTE**
6>
7>The initial APIs of this module are supported since API version 12. Newly added APIs will be marked with a superscript to indicate their earliest API version.
8
9
10The meanings of T and S in this topic are as follows:
11
12
13| Type  | Description                                    |
14| ---- | -------------------------------------- |
15| T    | Class, number, boolean, string, and arrays of these types.|
16| S    | number, boolean, string.                |
17
18
19## Modules to Import
20
21```ts
22import { AppStorageV2,PersistenceV2,UIUtils} from '@kit.ArkUI';
23```
24
25## AppStorageV2
26
27For details about how to use AppStorageV2, see [AppStorageV2: Storing Application-wide UI State](../../quick-start/arkts-new-appstoragev2.md).
28
29**Atomic service API**: This API can be used in atomic services since API version 12.
30
31**System capability**: SystemCapability.ArkUI.ArkUI.Full
32
33### connect
34
35static connect\<T extends object\>( <br>
36      type: TypeConstructorWithArgs\<T\>, <br>
37      keyOrDefaultCreator?: string | StorageDefaultCreator\<T\>, <br>
38      defaultCreator?: StorageDefaultCreator\<T\> <br>
39): T | undefined
40
41Stores key-value pair data in the application memory. If the given key already exists in [AppStorageV2](../../quick-start/arkts-new-appstoragev2.md), it returns the corresponding value; otherwise, it constructs a default value using the constructor for obtaining the default value and returns it.
42
43**Atomic service API**: This API can be used in atomic services since API version 12.
44
45**System capability**: SystemCapability.ArkUI.ArkUI.Full
46
47**Parameters**
48
49| Name  | Type  | Mandatory| Description              |
50| -------- | ------ | ---- | ---------------------- |
51| type | [TypeConstructorWithArgs\<T\>](#typeconstructorwithargst) | Yes  | Type. If no key is specified, the name of the type is used as the key.|
52| keyOrDefaultCreator | string \| [StorageDefaultCreator\<T\>](#storagedefaultcreatort) | No  | Key, or the constructor for obtaining the default value.|
53| defaultCreator | StorageDefaultCreator\<T\> | No  | Constructor for obtaining the default value.|
54
55>**NOTE**
56>
57>1. The second parameter is used when no key is specified, and the third parameter is used otherwise.
58>
59>2. If the data has been stored in AppStorageV2, you can obtain the stored data without using the default constructor. If the data has not been stored, you must specify a default constructor; otherwise, an application exception will be thrown.
60>
61>3. Ensure that the data types match the key. Connecting different types of data to the same key will result in an application exception.
62>
63>4. You are advised to use meaningful values for the key, with a length not exceeding 255 characters. The behavior of using illegal characters or empty characters is undefined.
64
65**Return value**
66
67| Type                                  | Description                                                        |
68| -------------------------------------- | ------------------------------------------------------------ |
69| T | Returns data if the creation or data acquisition from AppStorageV2 is successful; returns **undefined** otherwise.|
70
71**Example**
72
73```ts
74import { AppStorageV2 } from '@kit.ArkUI';
75
76@ObservedV2
77class SampleClass {
78  @Trace p: number = 0;
79}
80
81// Store the key-value pair with the key SampleClass and the value as a new instance of SampleClass() in memory, and assign it to variable as1.
82const as1: SampleClass | undefined = AppStorageV2.connect(SampleClass, () => new SampleClass());
83
84// Store the key-value pair with the key key_as2 and the value as a new instance of SampleClass() in memory, and assign it to variable as2.
85const as2: SampleClass = AppStorageV2.connect(SampleClass, 'key_as2', () => new SampleClass())!;
86
87// As the key SampleClass already exists in AppStorageV2, the value associated with the key is returned to variable as3.
88const as3: SampleClass = AppStorageV2.connect(SampleClass) as SampleClass;
89```
90
91### remove
92
93static remove\<T\>(keyOrType: string | TypeConstructorWithArgs\<T\>): void
94
95Removes the specified key-value pair from [AppStorageV2](../../quick-start/arkts-new-appstoragev2.md). If the specified key does not exist in AppStorageV2, the removal will fail.
96
97**Atomic service API**: This API can be used in atomic services since API version 12.
98
99**System capability**: SystemCapability.ArkUI.ArkUI.Full
100
101**Parameters**
102
103| Name  | Type  | Mandatory| Description              |
104| -------- | ------ | ---- | ---------------------- |
105| keyOrType | string \| TypeConstructorWithArgs\<T\> | Yes  | Key to be removed. If a type is specified, the key to be deleted is the name of that type.|
106
107>**NOTE**
108>
109>Attempting to remove a key that does not exist in AppStorageV2 will result in a warning.
110
111
112**Example**
113
114<!--code_no_check-->
115```ts
116// Assuming that there is a key named key_as2 in AppStorageV2, the following will remove the corresponding key-value pair from AppStorageV2.
117AppStorageV2.remove('key_as2');
118
119// Assuming that there is a key named SampleClass in AppStorageV2, the following will remove the corresponding key-value pair from AppStorageV2.
120AppStorageV2.remove(SampleClass);
121
122// Assuming there is no key named key_as1 in AppStorageV2, the following will result in a warning.
123AppStorageV2.remove('key_as1');
124```
125
126### keys
127
128static keys(): Array\<string\>
129
130Obtains all keys in [AppStorageV2](../../quick-start/arkts-new-appstoragev2.md).
131
132**Atomic service API**: This API can be used in atomic services since API version 12.
133
134**System capability**: SystemCapability.ArkUI.ArkUI.Full
135
136**Return value**
137
138| Type                                  | Description                                                        |
139| -------------------------------------- | ------------------------------------------------------------ |
140| Array\<string\> | All keys stored in AppStorageV2.|
141
142>**NOTE**
143>
144>The order of the keys in the Array is not sequential and does not correspond to the order in which the keys were inserted into AppStorageV2.
145
146**Example**
147
148```ts
149// Assuming there are two keys (key_as1 and key_as2) in AppStorageV2, the following will return an array containing these keys and assign it to keys.
150const keys: Array<string> = AppStorageV2.keys();
151```
152
153
154
155## PersistenceV2
156
157Inherits from [AppStorageV2](#appstoragev2). For details, see [PersistenceV2: Persisting Application State](../../quick-start/arkts-new-persistencev2.md).
158
159**Atomic service API**: This API can be used in atomic services since API version 12.
160
161**System capability**: SystemCapability.ArkUI.ArkUI.Full
162
163### globalConnect<sup>18+</sup>
164
165static globalConnect\<T extends object\>(type: ConnectOptions\<T\>): T | undefined
166
167Stores key-value pair data on the application disk. If the given key already exists in [PersistenceV2](../../quick-start/arkts-new-persistencev2.md), the corresponding value is returned. Otherwise, a default value is constructed using the default value constructor and returned. If **globalConnect** is used for an @ObservedV2 decorated object, changes to the object's @Trace properties will trigger automatic refresh of the associated object, while changes to non-@Trace properties will not. If necessary, the **PersistenceV2.save** API can be called to store the data manually.
168
169**Atomic service API**: This API can be used in atomic services since API version 18.
170
171**System capability**: SystemCapability.ArkUI.ArkUI.Full
172
173| Name  |Type  |Mandatory  | Description                                                     |
174| ------------- | ------------|-------------------|-------------------------- |
175| type    |[ConnectOptions\<T\>](#connectoptions18)    |Yes |**connect** parameter passed in. For details, see the description of **ConnectOptions**.|
176
177**Return value**
178
179|Type  |Description                |
180|----------|-----------------------------------|
181|T \| undefined    |Returns the data if creation or acquisition is successful; otherwise, returns **undefined**.   |
182
183> **NOTE**
184>
185> 1. The second parameter is used when no **key** is specified, and the third parameter is used otherwise (including when the second parameter is invalid).
186>
187> 2. If the data has been stored in PersistenceV2, you can obtain the stored data without using the default constructor. Otherwise, you must specify a default constructor to avoid application exceptions.
188>
189> 3. Ensure that the data types match the key. Matching different types of **globalConnect** data to the same key will result in an application exception.
190>
191> 4. You are advised to use meaningful values for keys. The values can contain letters, digits, and underscores (_) and a maximum of 255 characters. Using invalid characters or null characters will result in undefined behavior.
192>
193> 5. When matching the key with an [\@Observed](../../quick-start/arkts-observed-and-objectlink.md) object, specify the key or customize the **name** property.
194>
195> 6. The storage path for data is application-level. If different modules use the same key and the same encryption partition for **globalConnect**, only one copy of the data will be stored in the application.
196>
197> 7. If **globalConnect** is used with the same key but different encryption levels, the data will be stored with the encryption level of the first **globalConnect** call, and the data in **PersistenceV2** will also be stored with this encryption level.
198>
199> 8. Avoid using **connect** and **globalConnect** together, because they have different data copy paths. If they must be used together, make sure the keys are unique to avoid application crashes.
200>
201> 9. To enable EL5 encryption, configure the **ohos.permission.PROTECT_SCREEN_LOCK_DATA** field in the **module.json** file. For details, see [Declaring Permissions](../../security/AccessToken/declare-permissions.md).
202
203**Example**
204
205<!--code_no_check-->
206```ts
207import { PersistenceV2, Type, ConnectOptions } from '@kit.ArkUI';
208import { contextConstant } from '@kit.AbilityKit';
209
210@ObservedV2
211class SampleChild {
212  @Trace childId: number = 0;
213  groupId: number = 1;
214}
215
216@ObservedV2
217export class Sample {
218  // For complex objects, use the @Type decorator to ensure successful serialization.
219  @Type(SampleChild)
220  @Trace father: SampleChild = new SampleChild();
221}
222
223// If no key is provided, the type name is used as the key. If the encryption level is not specified, the default EL2 level is used.
224@Local p: Sample = PersistenceV2.globalConnect({type: Sample, defaultCreator:() => new Sample()})!;
225
226// Use the key 'global1' with an encryption level of EL1 for connection.
227@Local p1: Sample = PersistenceV2.globalConnect({type: Sample, key:'global1', defaultCreator:() => new Sample(), areaMode: contextConstant.AreaMode.EL1})!;
228
229// Use the key 'global2' with the constructor function for connection. If no encryption level is specified, the default EL2 level is used.
230@Local p2: Sample = PersistenceV2.globalConnect({type: Sample, key: 'global2', defaultCreator:() => new Sample()})!;
231
232// Use the key 'global3' with an explicit encryption level value (3 in this example) for connection. Note that values outside the valid range of 0-4 will cause application crashes.
233@Local p3: Sample = PersistenceV2.globalConnect({type: Sample, key:'global3', defaultCreator:() => new Sample(), areaMode: 3})!;
234
235```
236
237### save
238
239static save\<T\>(keyOrType: string | TypeConstructorWithArgs\<T\>): void
240
241Persists the specified key-value pair data once.
242
243**Atomic service API**: This API can be used in atomic services since API version 12.
244
245**System capability**: SystemCapability.ArkUI.ArkUI.Full
246
247**Parameters**
248
249| Name  | Type  | Mandatory| Description              |
250| -------- | ------ | ---- | ---------------------- |
251| keyOrType | string \| TypeConstructorWithArgs\<T\> | Yes  | Key to be persisted. If a type is specified, the key for persistence is the name of the type.|
252
253>**NOTE**
254>
255>Since changes to non-[\@Trace](../../quick-start/arkts-new-observedV2-and-trace.md) decorated data do not automatically trigger persistence through [PersistenceV2](../../quick-start/arkts-new-persistencev2.md), you can call this API to manually persist the data for the corresponding key when needed.
256>
257>It is useless to manually persist the keys that are not in the **connect** state in the memory.
258
259**Example**
260
261<!--code_no_check-->
262
263```ts
264// Assuming there is a key named key_as2 in PersistenceV2, the following will persist the data for this key-value pair.
265PersistenceV2.save('key_as2');
266
267// Assuming there is a key named SampleClass in PersistenceV2, the following will persist the data for this key-value pair.
268PersistenceV2.remove(SampleClass);
269
270// Assuming there is no key named key_as1 in PersistenceV2, this operation is meaningless.
271PersistenceV2.remove('key_as1');
272```
273
274### notifyOnError
275
276static notifyOnError(callback: PersistenceErrorCallback | undefined): void
277
278Called when persistence fails.
279
280**Atomic service API**: This API can be used in atomic services since API version 12.
281
282**System capability**: SystemCapability.ArkUI.ArkUI.Full
283
284**Parameters**
285
286| Name  | Type  | Mandatory| Description              |
287| -------- | ------ | ---- | ---------------------- |
288| callback | PersistenceErrorCallback \| undefined  | Yes  | Callback invoked when persistence fails.|
289
290**Example**
291
292```ts
293// Called when persistence fails.
294PersistenceV2.notifyOnError((key: string, reason: string, msg: string) => {
295  console.error(`error key: ${key}, reason: ${reason}, message: ${msg}`);
296});
297```
298
299## ConnectOptions<sup>18+</sup>
300
301**Atomic service API**: This API can be used in atomic services since API version 18.
302
303**System capability**: SystemCapability.ArkUI.ArkUI.Full
304
305|Name  |Type   |Read-Only  |Optional   |Description     |
306|--------|------------|------------|-----------|--------------|
307|type        | TypeConstructorWithArgs\<T\>   |No  |No  |Specified type.        |
308|key         | string   |No  |Yes  |key used for connection. If it is not provided, the name of the type is used as the key.            |
309|defaultCreator   | StorageDefaultCreator\<T\>   |No  |Yes  |Default constructor. It is recommended that this parameter be passed in. If **globalConnect** is called for the first time with a key and this parameter is not provided, an error will occur.|
310|areaMode      | contextConstant.AreaMode   |No  |Yes   |Encryption level, ranging from EL1 to EL5 (corresponding to the value from 0 to 4). For details, see [Obtaining and Modifying Encryption Levels](../../application-models/application-context-stage.md). If no value is passed in, the default EL2 level is used. Different encryption levels correspond to different storage paths. Values outside the valid range of 0-4 will cause the application to crash.|
311
312## UIUtils
313
314Provides APIs for handling data transformations related to state management.
315
316**Atomic service API**: This API can be used in atomic services since API version 12.
317
318**System capability**: SystemCapability.ArkUI.ArkUI.Full
319
320### getTarget
321
322static getTarget\<T extends object\>(source: T): T
323
324Obtains the original object from a proxy object wrapped by the state management framework. For details, see [getTarget API: Obtaining Original Objects](../../quick-start/arkts-new-getTarget.md).
325
326**Atomic service API**: This API can be used in atomic services since API version 12.
327
328**System capability**: SystemCapability.ArkUI.ArkUI.Full
329
330**Parameters**
331
332| Name| Type| Mandatory| Description    |
333| ------ | ---- | ---- | ------------ |
334| source | T    | Yes  | Source object.|
335
336**Return value**
337
338| Type| Description                                            |
339| ---- | ------------------------------------------------ |
340| T    | Original object of the source after the proxy added by the state management framework is removed.|
341
342**Example**
343
344```ts
345import { UIUtils } from '@kit.ArkUI';
346class NonObservedClass {
347  name: string = "Tom";
348}
349let nonObservedClass: NonObservedClass = new NonObservedClass();
350@Entry
351@Component
352struct Index {
353  @State someClass: NonObservedClass = nonObservedClass;
354  build() {
355    Column() {
356      Text(`this.someClass === nonObservedClass: ${this.someClass === nonObservedClass}`) // false
357      Text(`UIUtils.getTarget(this.someClass) === nonObservedClass: ${UIUtils.getTarget(this.someClass) ===
358        nonObservedClass}`) // true
359    }
360  }
361}
362```
363### makeObserved
364
365static makeObserved\<T extends object\>(source: T): T
366
367Converts ordinary unobservable data into observable data. For details, see [makeObserved API: Changing Unobservable Data to Observable Data](../../quick-start/arkts-new-makeObserved.md).
368
369**Atomic service API**: This API can be used in atomic services since API version 12.
370
371**System capability**: SystemCapability.ArkUI.ArkUI.Full
372
373**Parameters**
374
375| Name| Type| Mandatory| Description    |
376| ------ | ---- | ---- | ------------ |
377| source | T    | Yes  | Source object. It supports classes not decorated by @Observed or @ObserveV2, objects returned by **JSON.parse**, and classes decorated by @Sendable.<br>Array, Map, Set, and Date types are supported.<br>**collection.Array**, **collection.Set**, and **collection.Map** are supported.<br>For details, see [makeObserved API: Changing Unobservable Data to Observable Data](../../quick-start/arkts-new-makeObserved.md).|
378
379**Return value**
380
381| Type| Description                                            |
382| ---- | ------------------------------------------------ |
383| T    | Observable data.|
384
385**Example**
386
387```ts
388import { UIUtils } from '@kit.ArkUI';
389class NonObservedClass {
390  name: string = 'Tom';
391}
392
393@Entry
394@ComponentV2
395struct Index {
396  observedClass: NonObservedClass = UIUtils.makeObserved(new NonObservedClass());
397  nonObservedClass: NonObservedClass = new NonObservedClass();
398  build() {
399    Column() {
400      Text(`observedClass: ${this.observedClass.name}`)
401        .onClick(() => {
402          this.observedClass.name = 'Jane'; // This will trigger a UI update.
403        })
404      Text(`observedClass: ${this.nonObservedClass.name}`)
405        .onClick(() => {
406          this.nonObservedClass.name = 'Jane'; // This will not trigger a UI update.
407        })
408    }
409  }
410}
411```
412
413## StorageDefaultCreator\<T\>
414
415type StorageDefaultCreator\<T\> = () => T;
416
417Obtains the default constructor.
418
419**Atomic service API**: This API can be used in atomic services since API version 12.
420
421**System capability**: SystemCapability.ArkUI.ArkUI.Full
422
423**Return value**
424
425| Type| Description                                            |
426| ---- | ------------------------------------------------ |
427| () => T    | Default constructor.|
428
429**Example**
430
431```ts
432import { PersistenceV2 } from '@kit.ArkUI';
433
434@ObservedV2
435class SampleClass {
436  @Trace id: number = 0;
437  count: number = 1;
438}
439
440@ObservedV2
441class FatherSampleClass {
442  @Trace sampleClass: SampleClass = new SampleClass();
443}
444
445// Persist the key-value pair with the key SampleClass and the value as an instance of SampleClass(), and assign it to variable source.
446// StorageDefaultCreator refers to the function () => new FatherSampleClass().
447const source: FatherSampleClass | undefined = PersistenceV2.connect(FatherSampleClass, () => new FatherSampleClass());
448
449@Entry
450@Component
451struct SampleComp {
452  data: FatherSampleClass | undefined = source;
453
454  build() {
455    Column() {
456      Text(`${this.data?.sampleClass.id}`)
457    }
458  }
459}
460```
461
462## TypeConstructorWithArgs\<T\>
463
464Represents a class constructor that accepts arbitrary arguments.
465
466**Atomic service API**: This API can be used in atomic services since API version 12.
467
468**System capability**: SystemCapability.ArkUI.ArkUI.Full
469
470### new
471
472new(...args: any): T;
473
474**Atomic service API**: This API can be used in atomic services since API version 12.
475
476**System capability**: SystemCapability.ArkUI.ArkUI.Full
477
478**Parameters**
479
480| Name| Type| Mandatory| Description    |
481| ------ | ---- | ---- | ------------ |
482| ...args | any    | Yes  | Function arguments.  |
483
484**Return value**
485
486| Type| Description                                            |
487| ---- | ------------------------------------------------ |
488| T    | Instance of the T type.|
489
490**Example**
491
492```ts
493import { PersistenceV2 } from '@kit.ArkUI';
494
495@ObservedV2
496  // TypeConstructorWithArgs refers to the SampleClass constructor.
497class SampleClass {
498  @Trace id: number = 0;
499  count: number = 1;
500}
501
502@ObservedV2
503class FatherSampleClass {
504  @Trace sampleClass: SampleClass = new SampleClass();
505}
506
507// Persist the key-value pair with the key SampleClass and the value as an instance of SampleClass(), and assign it to variable source.
508const source: FatherSampleClass | undefined = PersistenceV2.connect(FatherSampleClass, () => new FatherSampleClass());
509
510@Entry
511@Component
512struct SampleComp {
513  data: FatherSampleClass | undefined = source;
514
515  build() {
516    Column() {
517      Text(`${this.data?.sampleClass.id}`)
518    }
519  }
520}
521```
522
523## PersistenceErrorCallback
524
525type PersistenceErrorCallback = (key: string, reason: 'quota' | 'serialization' | 'unknown', message: string) => void;
526
527Represents the callback invoked when persistence fails.
528
529**Atomic service API**: This API can be used in atomic services since API version 12.
530
531**System capability**: SystemCapability.ArkUI.ArkUI.Full
532
533**Parameters**
534
535| Name| Type| Mandatory| Description    |
536| ------ | ---- | ---- | ------------ |
537| key | string    | Yes  | Key associated with the error.  |
538|reason| 'quota' \| 'serialization' \| 'unknown'    | Yes  | Type of the error.  |
539| message | string    | Yes  | Additional information about the error.  |
540
541**Example**
542
543```ts
544import { PersistenceV2, Type } from '@kit.ArkUI';
545
546@ObservedV2
547class SampleChild {
548  @Trace id: number = 0;
549  count: number = 10;
550}
551
552@ObservedV2
553export class Sample {
554  // For complex objects, use the @Type decorator to ensure successful serialization.
555  @Type(SampleChild)
556  @Trace sampleChild: SampleChild = new SampleChild();
557}
558
559// Callback used to receive persistence errors.
560// PersistenceErrorCallback refers to (key: string, reason: string, msg: string) => {console.error(`error key: ${key}, reason: ${reason}, message: ${msg}`);}.
561PersistenceV2.notifyOnError((key: string, reason: string, msg: string) => {
562  console.error(`error key: ${key}, reason: ${reason}, message: ${msg}`);
563});
564
565@Entry
566@ComponentV2
567struct Index {
568  // Create a key-value pair with the key Sample in PersistenceV2 (if the key exists, the data in PersistenceV2 is returned) and associate it with data.
569  // Add @Local to decorate the data property that needs to change the connected object. (Changing the connected object is not recommended.)
570  @Local data: Sample = PersistenceV2.connect(Sample, () => new Sample())!;
571  pageStack: NavPathStack = new NavPathStack();
572
573  build() {
574    Text(`Index add 1 to data.id: ${this.data.sampleChild.id}`)
575      .fontSize(30)
576      .onClick(() => {
577        this.data.sampleChild.id++;
578      })
579  }
580}
581```
582
583## TypeConstructor\<T\>
584
585Class constructor.
586
587**Atomic service API**: This API can be used in atomic services since API version 12.
588
589**System capability**: SystemCapability.ArkUI.ArkUI.Full
590
591### new
592
593new(): T;
594
595**Return value**
596
597| Type| Description                                            |
598| ---- | ------------------------------------------------ |
599| T    | Instance of the T type.|
600
601**Atomic service API**: This API can be used in atomic services since API version 12.
602
603**System capability**: SystemCapability.ArkUI.ArkUI.Full
604
605**Example**
606
607```ts
608import { PersistenceV2, Type } from '@kit.ArkUI';
609
610@ObservedV2
611class SampleChild {
612  @Trace id: number = 0;
613  count: number = 10;
614}
615
616@ObservedV2
617export class Sample {
618  // For complex objects, use the @Type decorator to ensure successful serialization.
619  // TypeConstructor refers to SampleChild.
620  @Type(SampleChild)
621  @Trace sampleChild: SampleChild = new SampleChild();
622}
623
624@Entry
625@ComponentV2
626struct Index {
627  data: Sample = PersistenceV2.connect(Sample, () => new Sample())!;
628
629  build() {
630    Column() {
631      Text(`Index add 1 to data.id: ${this.data.sampleChild.id}`)
632        .fontSize(30)
633        .onClick(() => {
634          this.data.sampleChild.id++;
635        })
636    }
637  }
638}
639```
640
641## TypeDecorator
642
643type TypeDecorator = \<T\>(type: TypeConstructor\<T\>) => PropertyDecorator;
644
645Property decorator.
646
647**Atomic service API**: This API can be used in atomic services since API version 12.
648
649**System capability**: SystemCapability.ArkUI.ArkUI.Full
650
651**Parameters**
652
653| Name| Type| Mandatory| Description    |
654| ------ | ---- | ---- | ------------ |
655| type | [TypeConstructor\<T\>](#typeconstructort)    | Yes  | Type of the class property decorated.  |
656
657**Return value**
658
659| Type| Description                                            |
660| ---- | ------------------------------------------------ |
661| PropertyDecorator    | Property decorator.|
662
663**Example**
664
665```ts
666import { PersistenceV2, Type } from '@kit.ArkUI';
667
668@ObservedV2
669class SampleChild {
670  @Trace id: number = 0;
671  count: number = 10;
672}
673
674@ObservedV2
675export class Sample {
676  // For complex objects, use the @Type decorator to ensure successful serialization.
677  // TypeDecorator refers to @Type.
678  @Type(SampleChild)
679  @Trace sampleChild: SampleChild = new SampleChild();
680}
681
682@Entry
683@ComponentV2
684struct Index {
685  data: Sample = PersistenceV2.connect(Sample, () => new Sample())!;
686
687  build() {
688    Column() {
689      Text(`Index add 1 to data.id: ${this.data.sampleChild.id}`)
690        .fontSize(30)
691        .onClick(() => {
692          this.data.sampleChild.id++;
693        })
694    }
695  }
696}
697```
698