PersistenceV2持久化后数据无法读取的问题
==========================

#### 问题现象

**场景一**：PersistenceV2.connect/PersistenceV2.globalConnect执行在loadContent方法之前，导致再次进入应用持久化数据读取失败，每次都会重新创建新的数据的问题。

**场景二**：在使用PersistenceV2进行本地数据存储时，再次进入应用部分属性读取失败的问题。

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

@ObservedV2
class Sample {
  @Trace value?: string;
  @Trace num: number = 0;
}

@Entry
@ComponentV2
struct PageOne {
  @Local user: Sample =
    PersistenceV2.connect(Sample, 'Sample', () => new Sample())!;

  build() {
    Column() {
      Text(\`value: ${this.user.value}, num: ${this.user.num}\`)
        .fontSize(30);
      Button('connect')
        .onClick(() => {
          this.user.num = 2;
          this.user.value = 'SECOND';
        });
    };
  }
}

场景一问题效果预览：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/50/v3/l2Nc72wYQVetsJ67VBOX0g/zh-cn_image_0000002628407346.png?HW-CC-KV=V1&HW-CC-Date=20260709T134110Z&HW-CC-Expire=86400&HW-CC-Sign=B3C7D7BB5D78BC8EF3A110FC07BECF5B7FA314F500F0BD1883BAE687714CD23B "点击放大")

#### 背景知识

[PersistenceV2](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-persistencev2)提供状态变量持久化能力，开发者可以通过connect或者globalConnect绑定同一个key，在状态变量变化和应用冷启动时，实现持久化能力。与状态管理V1版本的[PersistentStorage](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-persiststorage)一致，必须要在EntryAbility.ets文件中的[loadContent](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-window-windowstage#loadcontent9)之后调用。其它PersistenceV2使用详情可查看官方文档：[PersistenceV2使用限制](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-persistencev2#使用限制)。

#### 解决方案

*   **场景一**：PersistenceV2.connect/PersistenceV2.globalConnect执行在loadContent方法之前，导致再次进入应用持久化数据读取失败，每次都会重新创建新的数据的问题。
    *   问题排查方案（以PersistenceV2.connect为例）：
        1.  检查是否本地持久化成功，若是没有持久化成功导致的读取失效，建议按照背景知识中的PersistenceV2使用限制检查是否存在使用错误的情况。
        2.  若本地存在持久化的数据，检查EntryAbility.ets文件内是否将PersistenceV2.connect写在了windowStage.loadContent方法之前。修改在windowStage.loadContent方法之后调用PersistenceV2.connect即可。
        3.  若无法直接判断PersistenceV2.connect是否在EntryAbility.ets中的windowStage.loadContent方法之前调用。使用Debug调试，分别将PersistenceV2.connect方法与EntryAbility.ets内windowStage.loadContent方法设置断点，查看PersistenceV2.connect与windowStage.loadContent执行顺序。
    *   若是存在第3点的情况，无法直接判断PersistenceV2.connect是否在EntryAbility.ets中的windowStage.loadContent方法之前调用。经过Debug调试，又确实是在windowStage.loadContent方法之前调用了PersistenceV2.connect。可以参考以下常见问题场景进行修改：
        
        | 
        场景一细分场景
        
         | 
        
        场景描述
        
         | 
        
        解决方案
        
         |
        | :-- | :-- | :-- |
        | 
        
        问题场景一
        
         | 
        
        例如封装了一个AccountUtil管理类来管理PersistenceV2本地持久化（AccountUtil中初始化PersistenceV2.connect方法），且在EntryAbility.ets文件内通过import方法将导入了该管理类的实例或者依赖该管理类的实例。那么在导入的过程中就会初始化AccountUtil实例，也就会导致PersistenceV2.connect在windowStage.loadContent方法之前调用。
        
         | 
        
        不要直接导入整个PersistenceV2的管理类，建议在使用时初始化该管理实例即可。若需要在EntryAbility.ets内使用本地持久化的数据，可以调用PersistenceV2.connect方法获取临时变量即可。
        
         |
        | 
        
        问题场景二
        
         | 
        
        存在多个模块时，通过import { xxx } from 'commonlib'的方式在EntryAbility.ets中导入了“xxx”实例，若PersistenceV2的管理类存在于commonlib模块中，且同时在“commonlib/src/Index.ets”文件中与“xxx”实例一起导出，也会导致PersistenceV2的管理类提前创建。
        
         | 
        
        1.  EntryAbility.ets内取消import { xxx } from 'commonlib'的导出方式，使用import { xxx } from 'commonlib/src/main/ets/util/xxx'的方式导入，避免执行commonlib模块中的Index.ets文件。
        2.  保留在EntryAbility.ets内import { xxx } from 'commonlib'的导出方式，取消在与“xxx”相同包中的“commonlib/src/Index.ets”文件中导出PersistenceV2.connect所在的管理类。或者将该管理类写在与“xxx”不同的包中，避免被优先创建。
        
         |
        
*   **场景二**：在使用PersistenceV2进行本地数据存储时，再次进入应用部分属性读取失败的问题。
    
    导致该问题的原因是读取数据时由于value属性是可选属性，导致未能准确读取。
    
    *   **方案一**：为保存的类增加一个constructor构建函数。
        
        import { PersistenceV2 } from '@kit.ArkUI';
        
        @ObservedV2
        class OptionOneSample {
          @Trace value?: string;
          @Trace num: number = 0;
        
          _// 构建函数赋值_
          constructor(value: string, num: number) {
            this.value = value;
            this.num = num;
          }
        }
        
        @Entry
        @ComponentV2
        struct OptionOne {
          @Local user: OptionOneSample =
            PersistenceV2.connect(OptionOneSample, 'Sample', () => new OptionOneSample('FIRST', 0))!;
        
          build() {
            Column() {
              Text(\`value: ${this.user.value}, num: ${this.user.num}\`)
                .fontSize(30);
              Button('connect')
                .onClick(() => {
                  this.user.num = 2;
                  this.user.value = 'SECOND';
                });
            }.width('100%');
          }
        }
        
        效果预览：
        
        ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/6/v3/np-RleA2Q9C2ABzZcKSsRg/zh-cn_image_0000002628567244.png?HW-CC-KV=V1&HW-CC-Date=20260709T134110Z&HW-CC-Expire=86400&HW-CC-Sign=94C3E05A1AD1FD00DE60B2F10C21E267A406B8018A83ECE4C6B6EFF7230DABE4 "点击放大")
        
    *   **方案二**：为value属性添加一个初始值。
        
        import { PersistenceV2 } from '@kit.ArkUI';
        
        @ObservedV2
        class OptionTwoSample {
          @Trace value: string = ''; _// 赋初始值_
          @Trace num: number = 0;
        }
        
        @Entry
        @ComponentV2
        struct OptionTwo {
          @Local user: OptionTwoSample =
            PersistenceV2.connect(OptionTwoSample, 'Sample', () => new OptionTwoSample())!;
        
          build() {
            Column() {
              Text(\`value: ${this.user.value}, num: ${this.user.num}\`)
                .fontSize(30);
              Button('connect')
                .onClick(() => {
                  this.user.num = 2;
                  this.user.value = 'SECOND';
                });
            }.width('100%');
          }
        }
        
        效果预览：
        
        ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/a9/v3/6IZF0-HHRlikSN9U4tUasA/zh-cn_image_0000002658926557.png?HW-CC-KV=V1&HW-CC-Date=20260709T134110Z&HW-CC-Expire=86400&HW-CC-Sign=DFBF8A58305F8DAFC262726C841AA100199C11B75CE102CAB4EA8B631326555F "点击放大")
        

#### 常见FAQ

Q：PersistenceV2持久化class中基本类型的数组需要加@Type吗？

A：PersistenceV2持久化class中基本类型（如number，boolean，string）的数组时，不需要使用[@Type装饰器](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-type)。