The state variable of ArrayList type cannot trigger UI rendering refresh after being changed.
Problem Description
When using the @State decorator on an ArrayList-type array variable, changes to the array elements do not trigger UI rendering. The problematic code is as follows:
import { ArrayList } from '@kit.ArkTS';
import { PromptAction } from '@ohos.arkui.UIContext';
@Entry
@Component
struct ArrayListPage {
@State numItems: ArrayList<string> = new ArrayList();
prompt: PromptAction = this.getUIContext().getPromptAction()
aboutToAppear(): void {
for (let index = 0; index < 2; index++) {
this.numItems.add(`index:${index}`)
}
}
build() {
Column() {
List() {
ForEach(this.numItems.convertToArray(), (item: string) => {
ListItem() {
Text(item)
.textAlign(TextAlign.Center)
.backgroundColor('#ff5bb8ff')
.width('100%')
}
})
}.margin({ left: '16px', right: '16px' })
Text(`Length of the state variable array:${this.numItems.length}`)
Button('Add').onClick(() => {
this.numItems.add('666')
this.prompt.openToast({
message: `Latest query for array length${this.numItems.length}`
})
})
}.width('100%')
.height('100%')
.padding(20)
}
}
The operational results are as follows:
Background Knowledge
- @State-decorated variables, also known as state variables. Once a variable is given the state attribute, the UI will undergo corresponding rendering changes when the state changes.
- ArrayList is a linear data structure implemented based on an array at its core.
Troubleshooting Process
After changing the variable, the UI rendering does not refresh. First, it is necessary to check whether the state variable contains multiple layers of nesting, as @State can only observe changes at the first level. In fact, the problematic code only contains one layer of nesting. Next, check whether the variable decorated with @State is reactive data, because changes in non-reactive data will not trigger a page re-render.
Analysis Conclusion
The Array obtained after using the convertToArray() method in ArrayList is just a regular array, not a state variable. Changes to the array are not observed by the UI and cannot trigger a UI rendering refresh. Only by directly overwriting the original value with a new ArrayList will the UI rendering be triggered. However, this method will cause parts that do not need to be refreshed to also refresh, affecting the application's performance, so it is not recommended.
Solution
It is recommended to use a responsive data structure, Array, to replace ArrayList. The example code is as follows:
import { PromptAction } from '@ohos.arkui.UIContext';
@Entry
@Component
struct ListPage {
@State numItems: Array<string> = [];
prompt: PromptAction = this.getUIContext().getPromptAction()
aboutToAppear(): void {
for (let index = 0; index < 2; index++) {
this.numItems.push(`index:${index}`)
}
}
build() {
Column() {
List() {
ForEach(this.numItems, (item: string) => {
ListItem() {
Text(item)
.textAlign(TextAlign.Center)
.backgroundColor('#ff5bb8ff')
.width('100%')
}
})
}.margin({ left: '16px', right: '16px' })
Text(`Length of the state variable array:${this.numItems.length}`)
Button('Add').onClick(() => {
this.numItems.push('index:666')
this.prompt.openToast({ message: `Latest query for array length${this.numItems.length}` })
})
}.width('100%')
.height('100%')
.padding(20)
}
}


Top comments (0)