鸿蒙Next状态管理优秀实践
2024/12/17 0:03:07
本文主要是介绍鸿蒙Next状态管理优秀实践,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
在鸿蒙Next应用开发中,高效的状态管理对于提升应用性能至关重要。本文将介绍一些状态管理的优秀实践,帮助开发者避免常见的低效开发场景,提升应用质量。
一、使用@ObjectLink代替@Prop减少不必要的深拷贝
问题描述
在父子组件数值传递中,若子组件不改变状态变量值,使用@Prop装饰状态变量会增加组件创建耗时。
反例
@Observed class ClassA { public c: number = 0; constructor(c: number ) { this.c = c; } } @Component struct PropChild { @Prop testNum: ClassA; // @Prop装饰状态变量会深拷贝 build() { Text(`PropChild testNum ${this.testNum.c}`) } } @Entry @Component struct Parent { @State testNum: ClassA[] = [new ClassA(1)]; build() { Column() { Text(`Parent testNum ${this.testNum[0].c}`) .onClick(() => { this.testNum[0].c += 1; }) // PropChild没有改变@Prop testNum: ClassA的值,所以这时最优的选择是使用@ObjectLink PropChild({ testNum: this.testNum[0] }) } } }
正例
@Observed class ClassA { public c: number = 0; constructor(c: number ) { this.c = c; } } @Component struct PropChild { @ObjectLink testNum: ClassA; // @ObjectLink装饰状态变量不会深拷贝 build() { Text(`PropChild testNum ${this.testNum.c}`) } } @Entry @Component struct Parent { @State testNum: ClassA[] = [new ClassA(1)]; build() { Column() { Text(`Parent testNum ${this.testNum[0].c}`) .onClick(() => { this.testNum[0].c += 1; }) // 当子组件不需要发生本地改变时,优先使用@ObjectLink,因为@Prop是会深拷贝数据,具有拷贝的性能开销,所以这个时候@ObjectLink是比@Link和@Prop更优的选择 PropChild({ testNum: this.testNum[0] }) } } }
二、不使用状态变量强行更新非状态变量关联组件
问题描述
开发者自定义UI状态变量来控制非状态变量关联组件更新,这种方式不合理且性能差。
反例
@Entry @Component struct CompA { @State needsUpdate: boolean = true; realState1: Array<number> = [4, 1, 3, 2]; // 未使用状态变量装饰器 realState2: Color = Color.Yellow; updateUI1(param: Array<number>): Array<number> { const triggerAGet = this.needsUpdate; return param; } updateUI2(param: Color): Color { const triggerAGet = this.needsUpdate; return param; } build() { Column({ space: 20 }) { ForEach(this.updateUI1(this.realState1), (item: Array<number>) => { Text(`${item}`) }) Text("add item") .onClick(() => { // 改变realState1不会触发UI视图更新 this.realState1.push(this.realState1[this.realState1.length - 1] + 1); // 触发UI视图更新 this.needsUpdate =!this.needsUpdate; }) Text("chg color") .onClick(() => { // 改变realState2不会触发UI视图更新 this.realState2 = this.realState2 == Color.Yellow? Color.Red : Color.Yellow; // 触发UI视图更新 this.needsUpdate =!this.needsUpdate; }) }.backgroundColor(this.updateUI2(this.realState2)) .width(200).height(500) } }
正例
@Component struct CompA { @State realState1: Array<number> = [4, 1, 3, 2]; @State realState2: Color = Color.Yellow; build() { Column({ space: 20 }) { ForEach(this.realState1, (item: Array<number>) => { Text(`${item}`) }) Text("add item") .onClick(() => { // 改变realState1触发UI视图更新 this.realState1.push(this.realState1[this.realState1.length - 1] + 1); }) Text("chg color") .onClick(() => { // 改变realState2触发UI视图更新 this.realState2 = this.realState2 == Color.Yellow? Color.Red : Color.Yellow; }) }.backgroundColor(this.realState2) .width(200).height(500) } }
三、精准控制状态变量关联的组件数
问题描述
同一个状态变量绑定多个同级组件属性,状态变量改变时会导致所有关联组件一起刷新,即使变化相同也会造成不必要刷新,影响性能。
反例
@Observed class Translate { translateX: number = 20; } @Component struct Title { @ObjectLink translateObj: Translate; build() { Row() { Image($r('app.media.icon')) .width(50) .height(50) .translate({ x: this.translateObj.translateX // this.translateObj.translateX used in two component both in Row }) Text("Title") .fontSize(20) .translate({ x: this.translateObj.translateX }) } } } @Entry @Component struct Page { @State translateObj: Translate = new Translate(); build() { Column() { Title({ translateObj: this.translateObj }) Stack() { } .backgroundColor("black") .width(200) .height(400) .translate({ x: this.translateObj.translateX // this.translateObj.translateX used in two components both in Column }) Button("move") .translate({ x: this.translateObj.translateX }) .onClick(() => { animateTo({ duration: 50 }, () => { this.translateObj.translateX = (this.translateObj.translateX + 50) % 150 }) }) } } }
正例
@Observed class Translate { translateX: number = 20; } @Component struct Title { build() { Row() { Image($r('app.media.icon')) .width(50) .height(50) Text("Title") .fontSize(20) } } } @Entry @Component struct Page1 { @State translateObj: Translate = new Translate(); build() { Column() { Title() Stack() { } .backgroundColor("black") .width(200) .height(400) Button("move") .onClick(() => { animateTo({ duration: 50 }, () => { this.translateObj.translateX = (this.translateObj.translateX + 50) % 150 }) }) } .translate({ // the component in Column shares the same property translate x: this.translateObj.translateX }) } }
四、合理控制对象类型状态变量关联的组件数量
将复杂对象定义为状态变量时,其某个成员属性变化会导致所有关联组件刷新,即使组件未直接使用该属性。建议合理拆分复杂对象,控制关联组件数量。
五、查询状态变量关联的组件数
可通过HiDumper查看状态变量关联的组件数进行性能优化,具体参考状态变量组件定位工具实践。
六、避免在for、while等循环逻辑中频繁读取状态变量
反例
@Entry @Component struct Index { @State message: string = ''; build() { Column() { Button('点击打印日志') .onClick(() => { for (let i = 0; i < 10; i++) { hilog.info(0x0000, 'TAG', '%{public}s', this.message); } }) .width('90%') .backgroundColor(Color.Blue) .fontColor(Color.White) .margin({ top: 10 }) } .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Center) .margin({ top: 15 }) } }
正例
@Entry @Component struct Index { @State message: string = ''; build() { Column() { Button('点击打印日志') .onClick(() => { let logMessage: string = this.message; for (let i = 0; i < 10; i++) { hilog.info(0x0000, 'TAG', '%{public}s', logMessage); } }) .width('90%') .backgroundColor(Color.Blue) .fontColor(Color.White) .margin({ top: 10 }) } .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Center) .margin({ top: 15 }) } }
七、建议使用临时变量替换状态变量
反例
import { hiTraceMeter } from '@kit.PerformanceAnalysisKit'; @Entry @Component struct Index { @State message: string = ''; appendMsg(newMsg: string) { // 性能打点 hiTraceMeter.startTrace('StateVariable', 1); this.message += newMsg; this.message += ';'; this.message += '<br/>'; hiTraceMeter.finishTrace('StateVariable', 1); } build() { Column() { Button('点击打印日志') .onClick(() => { this.appendMsg('操作状态变量'); }) .width('90%') .backgroundColor(Color.Blue) .fontColor(Color.White) .margin({ top: 10 }) } .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Center) .margin({ top: 15 }) } }
正例
import { hiTraceMeter } from '@kit.PerformanceAnalysisKit'; @Entry @Component struct Index { @State message: string = ''; appendMsg(newMsg: string) { // 性能打点 hiTraceMeter.startTrace('TemporaryVariable', 2); let message = this.message; message += newMsg; message += ';'; message += '<br/>'; this.message = message; hiTraceMeter.finishTrace('TemporaryVariable', 2); } build() { Column() { Button('点击打印日志') .onClick(() => { this.appendMsg('操作临时变量'); }) .width('90%') .backgroundColor(Color.Blue) .fontColor(Color.White) .margin({ top: 10 }) } .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Center) .margin({ top: 15 }) } }
通过遵循以上状态管理优秀实践,开发者可以在鸿蒙Next应用开发中更好地管理状态,提高应用性能,为用户提供更流畅的体验。
这篇关于鸿蒙Next状态管理优秀实践的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-21动态面包屑教程:新手入门指南
- 2024-12-21动态主题处理教程:新手必读指南
- 2024-12-21富文本编辑器教程:新手入门指南
- 2024-12-21前端项目部署教程:从零开始的全面指南
- 2024-12-21拖拽表格教程:轻松入门指南
- 2024-12-21Element-Plus教程:新手入门与实战指南
- 2024-12-21TagsView标签栏导航教程:轻松掌握标签栏导航
- 2024-12-21动态表格实战:新手入门教程
- 2024-12-21动态菜单项实战:一步步教你实现动态菜单项
- 2024-12-21动态面包屑实战:新手教程