Quản Lý Trạng Thái Hiệu Quả Trong Ứng Dụng HarmonyOS

Trong phát triển ứng dụng HarmonyOS, quản lý trạng thái hiệu quả đóng vai trò quan trọng trong việc nâng cao hiệu suất của ứng dụng. Bài viết này sẽ giới thiệu một số thực hành tốt nhất về quản lý trạng thái giúp nhà phát triển tránh các tình huống kém hiệu quả và cải thiện chất lượng ứng dụng.

Sử dụng @ObjectLink thay thế cho @Prop để giảm bớt sao chép sâu không cần thiết

Mô tả vấn đề

Khi truyền giá trị giữa các thành phần cha và con, nếu thành phần con không thay đổi giá trị biến trạng thái, sử dụng @Prop để trang trí biến trạng thái sẽ làm tăng thời gian tạo thành phần.

Ví dụ sai

@Observed
class ClassB {
  public d: number = 0;
  constructor(d: number ) {
    this.d = d;
  }
}
@Component
struct ChildComp {
  @Prop testVal: ClassB; // @Prop dẫn đến sao chép sâu
  build() {
    Text(`ChildComp testVal ${this.testVal.d}`)
  }
}
@Entry
@Component
struct Main {
  @State testVal: ClassB[] = [new ClassB(1)];
  build() {
    Column() {
      Text(`Main testVal ${this.testVal[0].d}`)
      .onClick(() => {
          this.testVal[0].d += 1;
        })
      // ChildComp không thay đổi giá trị @Prop testVal: ClassB, nên chọn @ObjectLink là tối ưu hơn
      ChildComp({ testVal: this.testVal[0] })
    }
  }
}

Ví dụ đúng

@Observed
class ClassB {
  public d: number = 0;
  constructor(d: number ) {
    this.d = d;
  }
}
@Component
struct ChildComp {
  @ObjectLink testVal: ClassB; // @ObjectLink không dẫn đến sao chép sâu
  build() {
    Text(`ChildComp testVal ${this.testVal.d}`)
  }
}
@Entry
@Component
struct Main {
  @State testVal: ClassB[] = [new ClassB(1)];
  build() {
    Column() {
      Text(`Main testVal ${this.testVal[0].d}`)
      .onClick(() => {
          this.testVal[0].d += 1;
        })
      // Khi thành phần con không cần thay đổi cục bộ, ưu tiên dùng @ObjectLink vì @Prop có chi phí sao chép
      ChildComp({ testVal: this.testVal[0] })
    }
  }
}

Không sử dụng biến trạng thái để ép buộc cập nhật thành phần liên quan đến biến phi trạng thái

Mô tả vấn đề

Sử dụng biến UI tùy chỉnh để điều khiển cập nhật thành phần liên quan đến biến phi trạng thái là cách làm không hợp lý và kém hiệu quả.

Ví dụ sai

@Entry
@Component
struct CompB {
  @State needsUpdate: boolean = true;
  realData1: Array<number> = [4, 1, 3, 2]; // Không sử dụng trình trang trí biến trạng thái
  realData2: Color = Color.Yellow;
  updateUI1(param: Array<number>): Array<number> {
    const triggerGet = this.needsUpdate;
    return param;
  }
  updateUI2(param: Color): Color {
    const triggerGet = this.needsUpdate;
    return param;
  }
  build() {
    Column({ space: 20 }) {
      ForEach(this.updateUI1(this.realData1),
        (item: Array<number>) => {
          Text(`${item}`)
        })
      Text("Thêm mục")
      .onClick(() => {
          this.realData1.push(this.realData1[this.realData1.length - 1] + 1);
          this.needsUpdate =!this.needsUpdate;
        })
      Text("Thay đổi màu")
      .onClick(() => {
          this.realData2 = this.realData2 == Color.Yellow? Color.Red : Color.Yellow;
          this.needsUpdate =!this.needsUpdate;
        })
    }.backgroundColor(this.updateUI2(this.realData2))
    .width(200).height(500)
  }
}

Ví dụ đúng

@Component
struct CompB {
  @State realData1: Array<number> = [4, 1, 3, 2];
  @State realData2: Color = Color.Yellow;
  build() {
    Column({ space: 20 }) {
      ForEach(this.realData1,
        (item: Array<number>) => {
          Text(`${item}`)
        })
      Text("Thêm mục")
      .onClick(() => {
          this.realData1.push(this.realData1[this.realData1.length - 1] + 1);
        })
      Text("Thay đổi màu")
      .onClick(() => {
          this.realData2 = this.realData2 == Color.Yellow? Color.Red : Color.Yellow;
        })
    }.backgroundColor(this.realData2)
    .width(200).height(500)
  }
}

Kiểm soát chính xác số lượng thành phần liên quan đến biến trạng thái

Mô tả vấn đề

Cùng một biến trạng thái được ràng buộc với nhiều thuộc tính thành phần đồng cấp, khi biến trạng thái thay đổi sẽ khiến tất cả các thành phần liên quan cùng làm mới, gây ra cập nhật không cần thiết và ảnh hưởng đến hiệu suất.

Ví dụ sai

@Observed
class TranslateObj {
  translateX: number = 20;
}
@Component
struct Header {
  @ObjectLink translateInstance: TranslateObj;
  build() {
    Row() {
      Image($r('app.media.icon'))
      .width(50)
      .height(50)
      .translate({
          x: this.translateInstance.translateX
        })
      Text("Header")
      .fontSize(20)
      .translate({
          x: this.translateInstance.translateX
        })
    }
  }
}
@Entry
@Component
struct PageMain {
  @State translateInstance: TranslateObj = new TranslateObj();
  build() {
    Column() {
      Header({
        translateInstance: this.translateInstance
      })
      Stack() {
      }
      .backgroundColor("black")
      .width(200)
      .height(400)
      .translate({
          x: this.translateInstance.translateX
        })
      Button("Di chuyển")
      .translate({
          x: this.translateInstance.translateX
        })
      .onClick(() => {
          animateTo({
            duration: 50
          }, () => {
            this.translateInstance.translateX = (this.translateInstance.translateX + 50) % 150
          })
        })
    }
  }
}

Ví dụ đúng

@Observed
class TranslateObj {
  translateX: number = 20;
}
@Component
struct Header {
  build() {
    Row() {
      Image($r('app.media.icon'))
      .width(50)
      .height(50)
      Text("Header")
      .fontSize(20)
    }
  }
}
@Entry
@Component
struct PageMain {
  @State translateInstance: TranslateObj = new TranslateObj();
  build() {
    Column() {
      Header()
      Stack() {
      }
      .backgroundColor("black")
      .width(200)
      .height(400)
      Button("Di chuyển")
      .onClick(() => {
          animateTo({
            duration: 50
          }, () => {
            this.translateInstance.translateX = (this.translateInstance.translateX + 50) % 150
          })
        })
    }
    .translate({
        x: this.translateInstance.translateX
      })
  }
}

Giới hạn số lượng thành phần liên quan đến đối tượng phức tạp làm biến trạng thái

Khi định nghĩa đối tượng phức tạp làm biến trạng thái, sự thay đổi của bất kỳ thuộc tính nào cũng sẽ làm tất cả các thành phần liên quan làm mới, dù chúng không trực tiếp sử dụng thuộc tính đó. Khuyến nghị tách nhỏ đối tượng phức tạp và kiểm soát số lượng thành phần liên quan.

Tránh đọc biến trạng thái thường xuyên trong vòng lặp for, while

Ví dụ sai

@Entry
@Component
struct IndexPage {
  @State messageLog: string = '';
  build() {
    Column() {
      Button('Nhấp để in nhật ký')
      .onClick(() => {
          for (let i = 0; i < 10; i++) {
            hilog.info(0x0000, 'TAG', '%{public}s', this.messageLog);
          }
        })
      .width('90%')
      .backgroundColor(Color.Blue)
      .fontColor(Color.White)
      .margin({
          top: 10
        })
    }
    .justifyContent(FlexAlign.Start)
    .alignItems(HorizontalAlign.Center)
    .margin({
          top: 15
        })
  }
}

Ví dụ đúng

@Entry
@Component
struct IndexPage {
  @State messageLog: string = '';
  build() {
    Column() {
      Button('Nhấp để in nhật ký')
      .onClick(() => {
          let logMessage: string = this.messageLog;
          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
        })
  }
}

Sử dụng biến tạm thời thay thế cho biến trạng thái

Ví dụ sai

import { hiTraceMeter } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct IndexPage {
  @State messageText: string = '';
  appendMsg(newMsg: string) {
    hiTraceMeter.startTrace('StateVariable', 1);
    this.messageText += newMsg;
    this.messageText += ';';
    this.messageText += '
'; hiTraceMeter.finishTrace('StateVariable', 1); } build() { Column() { Button('Nhấp để in nhật ký') .onClick(() => { this.appendMsg('Thao tác biến trạng thái'); }) .width('90%') .backgroundColor(Color.Blue) .fontColor(Color.White) .margin({ top: 10 }) } .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Center) .margin({ top: 15 }) } }

Ví dụ đúng

import { hiTraceMeter } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct IndexPage {
  @State messageText: string = '';
  appendMsg(newMsg: string) {
    hiTraceMeter.startTrace('TemporaryVariable', 2);
    let msg = this.messageText;
    msg += newMsg;
    msg += ';';
    msg += '
'; this.messageText = msg; hiTraceMeter.finishTrace('TemporaryVariable', 2); } build() { Column() { Button('Nhấp để in nhật ký') .onClick(() => { this.appendMsg('Thao tác biến tạm thời'); }) .width('90%') .backgroundColor(Color.Blue) .fontColor(Color.White) .margin({ top: 10 }) } .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Center) .margin({ top: 15 }) } }

Thẻ: HarmonyOS StateManagement optimization

Đăng vào ngày 28 tháng 6 lúc 23:32