Read the original article:What Can I Do If PersistentStorage Cannot Obtain Persistent Data?
What Can I Do If PersistentStorage Cannot Obtain Persistent Data?
Problem Description
When using PersistentStorage to operate on UI state variables, these variables are not correctly persisted. Each time the application is launched, the values are reinitialized. In the following example code, there are three UI state variables in the sample application, managed by LocalStorage, AppStorage, and PersistentStorage respectively. Among them, totalClickCount is managed by PersistentStorage and should be stored persistently. When the application is launched each time, the page should display the persisted data. However, in this example, the data cannot be retrieved properly and is always initialized to 0 upon each launch of the application.
Example code is as follows:
- src/main/ets/const/StorageKeyConst.ets.
export namespace StorageKeyConst {
// Application-level UI state storage
export const APP_PROP_KEY: string = 'APP_PROP';
// Page-level UI state storage
export const LOCAL_PROP_KEY: string = 'LOCAL_PROP';
// Persistent UI state storage
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 {
// Initialize application-level storage
AppStorage.setOrCreate(StorageKeyConst.APP_PROP_KEY, 0);
// Initialize application persistent storage
PersistentStorage.persistProp(StorageKeyConst.PERSIST_PROP_KEY, 0);
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
// Handling Exceptions
return;
}
});
}
}
- src/main/ets/pages/Index.ets.
import { StorageKeyConst } from '../const/StorageKeyConst';
import { Router } from '@kit.ArkUI';
let storage: LocalStorage = new LocalStorage();
@Entry(storage)
@Component
struct Index {
// Page No
@State pageNo: string = '';
// Page-level UI status storage (only saved on the current page)
@LocalStorageLink(StorageKeyConst.LOCAL_PROP_KEY)
pageClickCount: number = 0;
// Application-level UI state storage (Saved in the app memory and released after the app exits)
@StorageLink(StorageKeyConst.APP_PROP_KEY)
startupClickCount: number = 0;
// Persistent UI status storage (persistent storage, data retention after an app exits)
@StorageLink(StorageKeyConst.PERSIST_PROP_KEY)
totalClickCount: number = 0;
router: Router = this.getUIContext().getRouter()
aboutToAppear(): void {
// Current Page No
this.pageNo = this.router.getLength()
}
build() {
RelativeContainer() {
Column() {
Text(`Current Page No:${this.pageNo}`)
.margin(20)
Text(`Number of clicks on the current page:${this.pageClickCount}`)
.margin(10)
Text(`Number of clicks in this startup:${this.startupClickCount}`)
.margin(10)
Text(`Total Hits:${this.totalClickCount}`)
.margin(10)
Button('Click!')
.margin(10)
.onClick(() => {
// Click Count
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)
}
}
}
Background Knowledge
- LocalStorage: LocalStorage is a page-level UI state storage. Parameters received through the @Entry decorator can share the same LocalStorage instance within a page. LocalStorage supports state sharing among multiple pages within a UIAbility instance.
- AppStorage: AppStorage is a global UI state storage for an application. It is bound to the application's process and is created by the UI framework when the application starts, providing a central storage for the application's UI state properties.
- PersistentStorage: PersistentStorage is an optional singleton object in an application. This object is used to persistently store selected AppStorage properties to ensure that these properties retain their values after the application is restarted, just as they were when the application was closed. PersistentStorage is associated with a UI instance. Persistence operations can only be performed after the UI instance has been successfully initialized (i.e., when the callback passed to loadContent is called). Since the code in question calls PersistentStorage before this point, it leads to a failure in persistence. Refer to PersistentStorage: Persistently Storing UI State - Limitations.
Solution
There are two scenarios here. For debugging on a real device, you only need to modify the onWindowStageCreate function. However, since some APIs are not supported in the emulator, initializing PersistentStorage in onWindowStageCreate will fail. Therefore, you need to move the initialization code to the home page (Index.ets).
1.For the real device debugging scenario, modify the onWindowStageCreate function in src/main/ets/entryability/EntryAbility.ets:
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
// Initialize application-level storage
AppStorage.setOrCreate(StorageKeyConst.APP_PROP_KEY, 0);
// Initialize application persistent storage
PersistentStorage.persistProp(StorageKeyConst.PERSIST_PROP_KEY, 0);
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
// Handling Exceptions
return;
}
});
}
}
2.In the simulator debugging scenario, move the initialization function stored in the onWindowStageCreate function of src/main/ets/entryability/EntryAbility.ets to the beginning of the file src/main/ets/pages/Index.ets.
import { StorageKeyConst } from '../const/StorageKeyConst';
import { Router } from '@kit.ArkUI';
let storage: LocalStorage = new LocalStorage();
@Entry(storage)
@Component
struct Index {
// Page No
@State pageNo: string = '';
// Page-level UI status storage (only saved on the current page)
@LocalStorageLink(StorageKeyConst.LOCAL_PROP_KEY)
pageClickCount: number = 0;
// Application-level UI state storage (Saved in the app memory and released after the app exits)
@StorageLink(StorageKeyConst.APP_PROP_KEY)
startupClickCount: number = 0;
// Persistent UI status storage (persistent storage, data retention after an app exits)
@StorageLink(StorageKeyConst.PERSIST_PROP_KEY)
totalClickCount: number = 0;
router: Router = this.getUIContext().getRouter()
aboutToAppear(): void {
// Current Page No
this.pageNo = this.router.getLength()
}
build() {
RelativeContainer() {
Column() {
Text(`Current Page No:${this.pageNo}`)
.margin(20)
Text(`Number of clicks on the current page:${this.pageClickCount}`)
.margin(10)
Text(`Number of clicks in this startup:${this.startupClickCount}`)
.margin(10)
Text(`Total Hits:${this.totalClickCount}`)
.margin(10)
Button('Click!')
.margin(10)
.onClick(() => {
// Click Count
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)
}
}
}
Verification Result

This example supports API Version 20 Release and later versions.
This example supports HarmonyOS 6.0.0 Release SDK and later versions.
This example needs to be compiled and run using DevEco Studio 6.0.0 Release or later.
Top comments (0)