HarmonyOS Next中使用LazyForEach渲染列表,有没有遇到组件复用渲染异常问题?

代码如下:



class MyDataSource extends BasicDataSource {
  private dataArray: StringData[] = [];

  public totalCount(): number {
    return this.dataArray.length;
  }

  public getData(index: number): StringData {
    return this.dataArray[index];
  }

  public addData(index: number, data: StringData): void {
    this.dataArray.splice(index, 0, data);
    this.notifyDataAdd(index);
  }

  public pushData(data: StringData): void {
    this.dataArray.push(data);
    this.notifyDataAdd(this.dataArray.length - 1);
  }
}



class StringData {
  message: string;

  constructor(message: string) {
    this.message = message;
  }
}

@Entry
@ComponentV2
struct MyComponent {
  data: MyDataSource = new MyDataSource();

  aboutToAppear() {
    for (let i = 0; i <= 30; i++) {
      this.data.pushData(new StringData('Hello' + i));
    }
  }

  build() {
    List({ space: 3 }) {
      LazyForEach(this.data, (item: StringData, index: number) => {
        ListItem() {
          ChildComponent({ data: item })
            .onAppear(() => {
              console.log('onAppear: ' + item.message)
            })
        }
      }, (item: StringData, index: number) => index.toString())
    }.cachedCount(5)
  }
}

@Reusable
@Component
struct ChildComponent {
  @State data: StringData = new StringData('');

  aboutToAppear(): void {
    console.log('aboutToAppear: ' + this.data.message);
  }

  aboutToRecycle(): void {
    console.log('aboutToRecycle: ' + this.data.message);
  }

  // 对复用的组件进行数据更新
  aboutToReuse(params: Record<string, ESObject>): void {
    this.data = params.data as StringData;
    console.log('aboutToReuse: ' + this.data.message);
  }

  build() {
    Row() {
      Text(this.data.message).fontSize(50)
    }
  }
}

本文参与了 【 HarmonyOS NEXT 技术问答冲榜,等你来战!】欢迎正在阅读的你也加入。

阅读 160
avatarAI BotBETA

答案

在 HarmonyOS Next 中使用 LazyForEach 渲染列表时,确实可能会遇到组件复用渲染异常问题。这通常是由于组件复用机制在处理数据更新时未能正确更新组件状态导致的。

在你的代码中,LazyForEach 用于动态渲染列表,而 ChildComponent 被标记为可复用(@Reusable)。当数据发生变化(如添加新数据)时,LazyForEach 会尝试复用已存在的组件实例,并通过 aboutToReuse 方法传递新数据。然而,如果在这个过程中数据传递或组件状态更新不正确,就可能导致渲染异常。

为了解决这类问题,你可以检查以下几点:

  1. 确保数据正确传递:在 aboutToReuse 方法中,确保接收到的数据(params.data)是正确且完整的。
  2. 避免状态混乱:在 ChildComponent 中,确保在 aboutToReuse 方法中更新状态后,组件的渲染逻辑能够正确反映新的状态。
  3. 调试日志:利用 console.log 在关键位置打印日志,如 aboutToAppearaboutToRecycleaboutToReuse 方法中,以帮助跟踪组件的生命周期和数据变化。
  4. 检查数据源:确保 MyDataSource 类的数据更新逻辑正确,特别是在添加或删除数据时,要正确触发数据变更通知。
  5. 组件缓存策略List 组件的 cachedCount 属性设置了缓存的组件数量。根据你的应用场景调整这个值,以确保在数据变化时能够正确管理组件的复用和回收。

如果问题仍然存在,建议深入检查 LazyForEach 的实现细节,或考虑使用其他列表渲染方案,如手动管理组件实例和状态。

1 个回答

@Reusable与@ComponentV2混用会导致组件渲染异常。

在@ComponentV2装饰的组件MyComponent中,LazyForEach列表中使用了@Reusable装饰的组件ChildComponent,导致组件渲染失败,观察日志可以看到组件触发了onAppear,但是没有触发aboutToAppear。

将@ComponentV2修改为@Component可以修复渲染异常。修复后,当滑动事件触发组件节点下树时,对应的可复用组件ChildComponent从组件树上被加入到复用缓存中而不是被销毁,并触发aboutToRecycle事件,打印日志信息。当滑动需要显示新的节点时,会将可复用的组件从复用缓存中重新加入到节点树,并触发aboutToReuse刷新组件数据,并打印日志信息。

本文参与了 【 HarmonyOS NEXT 技术问答冲榜,等你来战!】欢迎正在阅读的你也加入。

logo
HarmonyOS
子站问答
访问
宣传栏