使用PersistentStorage对UI状态变量操作时,该变量不能正确持久化,每次启动应用时数值都被重新初始化。
如下示例代码,示例应用中有3个UI状态变量,分别使用LocalStorage、AppStorage、PersistentStorage进行管理。其中totalClickCount由PersistentStorage进行管理,会持久化存储,应用每次启动时页面应当展示持久化的数据,但示例中无法正常获取,每次启动应用时都会被初始化为0。
问题效果预览:

问题代码示例参考如下:
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; } }); } }
import { StorageKeyConst } from '../const/StorageKeyConst'; import { Router } from '@kit.ArkUI'; let storage: LocalStorage = new LocalStorage(); @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; router: Router = this.getUIContext().getRouter() aboutToAppear(): void { // 当前页面序号 this.pageNo = this.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(() => { this.router.pushUrl({ url: 'pages/Index' }) }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) } } }

PersistentStorage和UI实例相关联,持久化操作需要在UI实例初始化成功后(即loadContent传入的回调被调用时)才可以被调用,由于问题代码中PersistentStorage早于该时机调用,所以会导致持久化失败。参考PersistentStorage:持久化存储UI状态 - 限制条件。
通过以上分析可以得出结论:此问题关键点在于PersistentStorage初始化时机不对。因此只需要修改EntryAbility.ets中的onWindowStageCreate函数,在windowStage加载页面完成回调函数中初始化应用持久化存储即可。关键代码修改示例如下:
onWindowStageCreate(windowStage: window.WindowStage): void { // Main window is created, set main page for this ability hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); windowStage.loadContent('pages/Index', (err) => { if (err.code) { hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); return; } // 初始化应用级存储 AppStorage.setOrCreate(StorageKeyConst.APP_PROP_KEY, 0); // 初始化应用持久化存储 PersistentStorage.persistProp(StorageKeyConst.PERSIST_PROP_KEY, 0); hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); }); }
完整示例参考如下:
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'; }
import { ConfigurationConstant, UIAbility } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { window } from '@kit.ArkUI'; import { StorageKeyConst } from '../const/StorageKeyConst'; const DOMAIN = 0x0000; export default class EntryAbility extends UIAbility { onCreate(): void { try { this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); } catch (err) { hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); } hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); } onDestroy(): void { hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); } onWindowStageCreate(windowStage: window.WindowStage): void { // Main window is created, set main page for this ability hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); windowStage.loadContent('pages/Index', (err) => { if (err.code) { hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); return; } // 初始化应用级存储 AppStorage.setOrCreate(StorageKeyConst.APP_PROP_KEY, 0); // 初始化应用持久化存储 PersistentStorage.persistProp(StorageKeyConst.PERSIST_PROP_KEY, 0); hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); }); } onWindowStageDestroy(): void { // Main window is destroyed, release UI related resources hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); } onForeground(): void { // Ability has brought to foreground hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); } onBackground(): void { // Ability has back to background hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); } }
import { StorageKeyConst } from '../const/StorageKeyConst'; import { Router } from '@kit.ArkUI'; let storage: LocalStorage = new LocalStorage(); @Entry(storage) @Component export 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; router: Router = this.getUIContext().getRouter(); aboutToAppear(): void { // 当前页面序号 this.pageNo = this.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(() => { this.router.pushUrl({ url: 'pages/Index' }); }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) } } }
PersistentStorage需要在首页加载后进行初始化才能正确绑定UI状态,因此一定要在windowStage.loadContent之后进行初始化,否则无法正确获取已存储的数据,或者会导致将已存储的数据覆盖。