Problem Description
A state variable is declared using the @Provide decorator, and data is modified using methods provided by other classes. However, this does not trigger a UI refresh, and the data on the page remains unchanged. The following is a sample code for the problem:
Index.ets page
// Index.ets
import currentPlayInfo, { PlayInfo } from './PlayInfo'
import player from './AVPlayer'
@Entry
@Component
struct Index {
@Provide('pageStack') pageStack: NavPathStack = new NavPathStack()
@Provide('playInfo') playInfo: PlayInfo = currentPlayInfo
build() {
Navigation(this.pageStack) {
Column() {
if (this.playInfo.isPlaying) {
Text('Playing: ' + this.playInfo.title)
.fontSize(30)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
} else {
Text('Not playing')
.fontSize(30)
}
Text('Change PlayInfo')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
player.play();
})
}
.height('100%')
.width('100%')
}
.hideTitleBar(true)
}
}
Encapsulate the PlayInfo class and export the global instance object to the Index.ets page
// PlayInfo.ets
export class PlayInfo {
isPlaying: boolean = false
title: string = ''
}
let currentPlayInfo = new PlayInfo();
export default currentPlayInfo as PlayInfo;
Encapsulates the AVPlayer method class to modify the playback data.
// AVPlayer.ets
import currentPlayInfo from './PlayInfo'
class AVPlayer {
play() {
currentPlayInfo.isPlaying = !currentPlayInfo.isPlaying;
currentPlayInfo.title = 'Track ' + Math.round(Math.random() * 100);
}
}
let player = new AVPlayer();
export default player as AVPlayer;
When you click the "Change PlayInfo" text, you want the text "Not playing" to be updated to "Playing song XX". The problem phenomenon is shown in the figure below:
Background Knowledge
-
State Management Overview :
In a declarative UI programming framework, the UI is the result of the program state. The user builds a UI model in which the runtime state of the application is a parameter. When the parameter changes, the UI, as the return result, will also change accordingly. The re-rendering of the UI caused by these runtime state changes is collectively referred to as the state management mechanism in ArkUI.
Custom components have variables, and variables must be decorated with decorators to become state variables. Changes in state variables will cause the UI rendering to refresh. If state variables are not used, the UI can only be rendered at initialization and will not be refreshed subsequently. The following figure shows the relationship between State and View (UI).
- View (UI): UI rendering refers to mapping the UI description in the build method and the UI description in the
@Builderdecorated method to the interface. - State: The data that drives UI updates. Users change state data by triggering component events. Changes to state data cause the UI to re-render.
- State variables: Variables decorated with state decorators. Changes to state variable values will cause UI rendering updates. Example: @State num: number = 1, where @State is a state decorator and num is a state variable.
Regular variables: variables that are not decorated by state decorators, usually used for auxiliary calculations. Its changes will never cause the UI to refresh
@Provide/@Comsume decorator : This decorator is a state management decorator that can realize the sharing and two-way synchronization of component data with descendant components, and can realize synchronous refresh of UI when modification occurs.
Troubleshooting Process
- In the ArkUI programming framework, page refresh requires refreshing the UI interface by modifying the state variables decorated by the state decorator.
- The @Provide decorator proxies the decorated state variable to a proxy object. In the problematic code example, the proxy object is playInfo, not currentPlayInfo. Therefore, although the play() method in the AVPlayer class modifies the currentPlayInfo object, the currentPlayInfo object is a regular variable and therefore cannot refresh the UI.
Analysis Conclusion
play() modifies the normal variable currentPlayInfo, not the state variable playInfo, so it will not trigger a UI refresh. play() needs to modify the state variable playInfo to refresh the UI.
Solution
Change the normal variable currentPlayInfo that is modified by the play() method in the AVPlayer class to the state variable playInfo. Since the state variable playInfo is not a global instance object and cannot be modified by importing it, override the play() method and pass in the state variable playInfo when calling it to modify it. Modify it as follows:
1.Rewrite the play() method to a function that requires parameters.
// AVPlayer.ets
class AVPlayer {
playNew(playInfo: PlayInfo) {
playInfo.isPlaying = !playInfo.isPlaying;
playInfo.title = 'Track ' + Math.round(Math.random() * 100);
}
}
2.Pass the state variable playInfo to implement click modification and refresh the UI interface.
/ Index.ets
Text('Change PlayInfo')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
// The state variable needs to be modified to drive UI updates
player.playNew(this.playInfo as PlayInfo);
})
- ArkUI is a declarative UI programming framework based on the MVVM pattern. It drives UI updates through changes in state variables. Therefore, when the UI needs to be updated, the corresponding state variables need to be modified.
- Variables or objects that are not decorated by decorators are mainly used for type declaration, initialization, calculation, etc. Modifying such ordinary variables cannot directly cause the refresh of UI data.
Verification Result
Code running effect diagram :
Limitations or Considerations
- This example supports API Version 19 Release and above.
- This example supports HarmonyOS 5.1.1 Release SDK and above.
- This example requires DevEco Studio 5.1.1 Release and above to compile and run


Top comments (0)