HarmonyOS鸿蒙Next中PersistentStorage无法获取持久化的数据如何解决

HarmonyOS鸿蒙Next中PersistentStorage无法获取持久化的数据如何解决

【问题现象】

使用PersistentStorage对UI状态变量操作时,该变量不能正确持久化,每次启动应用时数值都被重新初始化。

如下示例代码,示例应用中有3个UI状态变量,分别使用LocalStorage、AppStorage、PersistentStorage进行管理。其中totalClickCount由PersistentStorage进行管理,会持久化存储,应用每次启动时应当自动刷新为存储的数据,但示例中无法正常获取,每次启动应用时都会被初始化为0。

应用启动截图如下:

点击放大

示例代码如下:

  • src/main/ets/const/StorageKeyConst.ets
export namespace StorageKeyConst {
  // 应用级UI状态存储
  export const APP_PROP_KEY: string = "APP_PROP";

  // 页面级UI状态存储
  export const LOCAL_PROP_KEY: string = "LOCAL_PROP";

  // 持久化UI状态存储
  export const PERSIST_PROP_KEY: string = "PERSIST_PROP";
}
  • src/main/ets/entryability/EntryAbility.ets
export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage): void {
    // 初始化应用级存储
    AppStorage.setOrCreate(StorageKeyConst.APP_PROP_KEY, 0);
    // 初始化应用持久化存储
    PersistentStorage.persistProp(StorageKeyConst.PERSIST_PROP_KEY, 0);
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        // 处理异常
        return;
      }
    });
  }
}
  • src/main/ets/pages/Index.ets
let storage: LocalStorage = new LocalStorage();

[@Entry](/user/Entry)(storage)
@Component
struct Index {
  // 页面序号
  @State pageNo: string = "";
  // 页面级UI状态存储(仅保存在当前页面)
  @LocalStorageLink(StorageKeyConst.LOCAL_PROP_KEY)
  pageClickCount: number = 0;
  // 应用级UI状态存储(保存在应用内存中,应用退出后释放)
  @StorageLink(StorageKeyConst.APP_PROP_KEY)
  startupClickCount: number = 0;
  // 持久化UI状态存储(持久化保存,应用退出后数据保留)
  @StorageLink(StorageKeyConst.PERSIST_PROP_KEY)
  totalClickCount: number = 0;

  aboutToAppear(): void {
    // 当前页面序号
    this.pageNo = router.getLength()
  }

  build() {
    RelativeContainer() {
      Column() {
        Text(`当前页面序号:${this.pageNo}`)
          .margin(20)
        Text(`当前页面点击次数:${this.pageClickCount}`)
          .margin(10)
        Text(`本次启动点击次数:${this.startupClickCount}`)
          .margin(10)
        Text(`总计点击次数:${this.totalClickCount}`)
          .margin(10)
        Button("Click!")
          .margin(10)
          .onClick(() => {
            // 点击计数
            this.pageClickCount++
            this.startupClickCount++
            this.totalClickCount++
          })
        Button("New Page")
          .margin(10)
          .onClick(() => {
            router.pushUrl({ url: "pages/Index" })
          })
      }
    }
  }
}

【背景知识】

  • LocalStorage:LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。
  • AppStorage:AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。
  • PersistentStorage:PersistentStorage是应用程序中的可选单例对象。此对象的作用是持久化存储选定的AppStorage属性,以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同。

【定位思路】

PersistentStorage和UI实例相关联,持久化操作需要在UI实例初始化成功后(即loadContent传入的回调被调用时)才可以被调用,早于该时机调用会导致持久化失败。参考链接:PersistentStorage:持久化存储UI状态 - 限制条件

【解决方案】

此处分两个场景,真机调试只需要修改onWindowStageCreate函数即可,模拟器由于部分API不支持,在onWindowStageCreate无法初始化PersistentStorage,需要将初始化的代码移动到首页(Index.ets)中。

(1)真机调试场景,修改src/main/ets/entryability/EntryAbility.ets中的onWindowStageCreate函数:

onWindowStageCreate(windowStage: window.WindowStage): void {
  windowStage.loadContent('pages/Index', (err) => {
    if (err.code) {
      // 处理异常
      return;
    }

    // 初始化应用级存储
    AppStorage.setOrCreate(StorageKeyConst.APP_PROP_KEY, 0);
    // 初始化应用持久化存储
    PersistentStorage.persistProp(StorageKeyConst.PERSIST_PROP_KEY, 0);
  });
}

(2)模拟器调试场景,将src/main/ets/entryability/EntryAbility.ets中的onWindowStageCreate函数中存储初始化函数移到src/main/ets/pages/Index.ets中文件头部:

let storage: LocalStorage = new LocalStorage();

// 初始化应用级存储
AppStorage.setOrCreate(StorageKeyConst.APP_PROP_KEY, 0);
// 初始化应用持久化存储
PersistentStorage.persistProp(StorageKeyConst.PERSIST_PROP_KEY, 0);

[@Entry](/user/Entry)(storage)
@Component
struct Index {
  // 页面序号
  @State pageNo: string = "";
  // 页面级UI状态存储(仅保存在当前页面)
  @LocalStorageLink(StorageKeyConst.LOCAL_PROP_KEY)
  pageClickCount: number = 0;
  // 应用级UI状态存储(保存在应用内存中,应用退出后释放)
  @StorageLink(StorageKeyConst.APP_PROP_KEY)
  startupClickCount: number = 0;
  // 持久化UI状态存储(持久化保存,应用退出后数据保留)
  @StorageLink(StorageKeyConst.PERSIST_PROP_KEY)
  totalClickCount: number = 0;

  aboutToAppear(): void {
    // 当前页面序号
    this.pageNo = router.getLength()
  }

  build() {
    // Index页面build函数
  }
}

【总结】

PersistentStorage需要在首页加载后进行初始化才能正确绑定UI状态,对于真机调试一定要在windowStage.loadContent之后进行初始化,模拟器则要在首页的page中进行初始化,否则无法正确获取已存储的数据,或者将已存储的数据覆盖。


更多关于HarmonyOS鸿蒙Next中PersistentStorage无法获取持久化的数据如何解决的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中PersistentStorage无法获取持久化的数据如何解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,如果PersistentStorage无法获取持久化的数据,可能是由于以下原因:

  1. 数据未正确存储,确保在存储数据时使用了正确的键值对,并且数据已成功写入。
  2. 数据存储路径错误,检查存储路径是否正确配置,确保应用有权限访问该路径。
  3. 数据读取时机不当,确保在数据存储完成后进行读取操作,避免在数据未完全写入时读取。
  4. 应用生命周期问题,确保在应用启动或恢复时进行数据读取,避免在应用销毁或暂停时读取。
  5. 数据存储格式不匹配,确保读取时使用的数据类型与存储时一致。
  6. 系统缓存问题,尝试清除应用缓存或重启设备后再次读取数据。
  7. 系统版本兼容性问题,检查当前系统版本是否支持PersistentStorage功能,确保系统版本符合要求。
  8. 应用权限问题,确保应用已获取必要的存储权限,避免因权限不足导致数据无法读取。
  9. 数据存储空间不足,检查设备存储空间是否充足,避免因空间不足导致数据无法存储或读取。
  10. 系统异常或bug,检查系统日志或更新系统版本,排除系统异常或bug导致的问题。
回到顶部