HarmonyOS鸿蒙Next中数组改变foreach渲染图片出现闪烁

HarmonyOS鸿蒙Next中数组改变foreach渲染图片出现闪烁

目前有一个数组A其中包含了数组B(数组A的属性)

  1. 使用数组A遍历三个按钮

  2. 使用数组B去渲染图片

  3. 当点击A渲染的按钮时获取index,根据index去切换数组B

~~ ForEach(this.cardListArr[this.SelectIndex].couponInfoVoList,()=>{})

当我们切换时数组B所渲染的图片出现闪烁

5 回复

可使用图片的syncLoad方法,参考地址:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-image-V5#syncload8

interface FirstArrInterface {
  NameAndId: string
  SecondArr: Array<SecondArrInterface>
}

class SecondArrInterface {
  NameAndId: string = ""
  Num: number = 0
  Desc: string = ""
}

class BasicDataSource implements IDataSource {
  private listeners: DataChangeListener[] = [];
  private originDataArray: SecondArrInterface[] = [];

  public totalCount(): number {
    return 0;
  }
  public getData(index: number): SecondArrInterface {
    return this.originDataArray[index];
  }
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      console.info('add listener');
      this.listeners.push(listener);
    }
  }
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      console.info('remove listener');
      this.listeners.splice(pos, 1);
    }
  }
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded();
    })
  }
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index);
    })
  }
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChange(index);
    })
  }
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDelete(index);
    })
  }
  notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener => {
      listener.onDataMove(from, to);
    })
  }
}

class MyDataSource extends BasicDataSource {
  private dataArray: SecondArrInterface[] = [];
  public totalCount(): number {
    return this.dataArray.length;
  }
  public getData(index: number): SecondArrInterface{
    return this.dataArray[index];
  }
  public addData(index: number, data: SecondArrInterface): void {
    this.dataArray.splice(index, 0, data);
    this.notifyDataAdd(index);
  }
  public pushData(data: SecondArrInterface): void {
    this.dataArray.push(data);
    this.notifyDataAdd(this.dataArray.length - 1);
  }
}

@Component
struct Index {
  @State FirstArr: Array<FirstArrInterface> = []
  @State SecondArr: Array<SecondArrInterface> = []
  @State SelectIndex: number = 0
  @State data: MyDataSource = new MyDataSource();

  initData() {
    this.FirstArr = [
      {
        NameAndId: "FirstArr1",
        SecondArr: [
          {
            NameAndId: "SecondArr1",
            Num: 1,
            Desc: "SecondArr1",
          },
          {
            NameAndId: "SecondArr1.2",
            Num: 1.2,
            Desc: "SecondArr1.2",
          }
        ]
      },
      {
        NameAndId: "FirstArr2",
        SecondArr: [{
          NameAndId: "SecondArr2",
          Num: 2,
          Desc: "SecondArr2",
        }, {
          NameAndId: "SecondArr2.2",
          Num: 2.2,
          Desc: "SecondArr2.2",
        }]
      },
      {
        NameAndId: "FirstArr3",
        SecondArr: [{
          NameAndId: "SecondArr3",
          Num: 3,
          Desc: "SecondArr3",
        }]
      },
    ]
    this.SecondArr = this.FirstArr[this.SelectIndex].SecondArr
  }

  initData2() {
    this.SecondArr = this.FirstArr[this.SelectIndex].SecondArr
  }

  onPageShow(): void {
    this.initData()
  }

  build() {
    Column({ space: 14 }) {
      Row() {
        ForEach(this.FirstArr, (item: FirstArrInterface, index: number) => {
          Button(item.NameAndId).onClick(() => {
            this.SelectIndex = index
            this.initData2()
          })
        }, (item: FirstArrInterface) => item.NameAndId)
      }
      .justifyContent(FlexAlign.SpaceAround)
      .margin({
        top: 20
      })
      .padding({
        top: 15,
        bottom: 15,
      })
      .backgroundColor("#cecece")
      .width("100%")

      Row() {
        ForEach(this.SecondArr, (item: SecondArrInterface) => {
         itemView({item: item})
        }, (item: SecondArrInterface) => item.NameAndId)
      }
      .padding({
        top:10,
        bottom:10
      })
      .justifyContent(FlexAlign.SpaceBetween)
      .width("100%")
      .backgroundColor("#993366")

    }
    .height('100%')
    .width('100%')
  }
}

@Component
struct itemView {
  @ObjectLink item:SecondArrInterface
  build() {
    Column() {
      Text(this.item.Desc)
        .position({
          top: 12,
          left: 12
        })
        .zIndex(2)
      Text(this.item.Num + "")
        .position({
          top: 12,
          right: 12
        })
        .zIndex(2)
      Image($r("app.media.ceshi"))
        .width("167")
        .height("67")
        .syncLoad(true)
    }
    .width("167")
    .height("67")
  }
}

更多关于HarmonyOS鸿蒙Next中数组改变foreach渲染图片出现闪烁的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


syncLoad,我试了下,滑动卡顿了都,这个方法还是不行,

你是在模拟器还是真机上运行的,syncload在传true的话有缓存的情况下不闪的,

如果syncload不可行,给图片设置下缓存

onPageShow() {
  // 设置解码前图片数据内存缓存上限为100MB (100MB=100*1024*1024B=104857600B)
  app.setImageRawDataCacheSize(104857600)
  console.info('Application onPageShow')
}

在HarmonyOS鸿蒙Next中,数组改变时使用foreach渲染图片出现闪烁,通常是由于UI刷新机制引起的。HarmonyOS的UI框架在数组数据发生变化时,会重新渲染相关的UI组件。如果数组频繁变化,且foreach中的图片组件没有正确处理数据变更,可能会导致图片闪烁。

解决方法可以通过以下方式优化:

  1. 使用@State@Link绑定数据:确保数组数据的变化能够正确触发UI更新,避免不必要的重新渲染。@State用于组件内部状态管理,@Link用于父子组件间的状态同步。

  2. 优化foreach中的组件:在foreach中渲染图片时,确保每个图片组件都有唯一的key属性。这样可以避免框架误判组件的变化,减少不必要的重新渲染。

  3. 使用LazyForEach代替foreachLazyForEach是鸿蒙提供的优化列表渲染的组件,它可以延迟加载和销毁不在可视区域的组件,减少性能开销和渲染闪烁。

  4. 图片缓存:使用鸿蒙提供的图片缓存机制,避免重复加载图片资源。可以通过Image组件的cached属性或使用ImageCache进行图片缓存管理。

  5. 减少数据变更频率:如果数组变化频繁,可以考虑合并多次数据变更,减少UI刷新的次数。

通过这些优化手段,可以有效减少数组改变时foreach渲染图片出现的闪烁问题。

在HarmonyOS鸿蒙Next中,如果数组改变后使用foreach渲染图片时出现闪烁,可能是由于频繁的数组更新导致UI重绘。建议优化数据更新机制,减少不必要的重绘。可以通过以下方式解决:

  1. 数据绑定优化:确保数据变化时只更新必要的部分,而不是整个数组。
  2. 使用List组件:List组件内置了高效的渲染机制,能够更好地处理动态数据。
  3. 图片缓存:使用Image组件的缓存机制,减少图片加载时间。
  4. 异步更新:将数据更新操作放到异步线程中,避免阻塞UI线程。

通过这些优化,可以有效减少闪烁问题。

回到顶部