HarmonyOS鸿蒙Next中封装LazyForEach懒加载

HarmonyOS鸿蒙Next中封装LazyForEach懒加载 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-lazyforeach

概念

用于页面数据循环的一个组件。可以实现数据懒加载或者动态加载效果。

以屏幕可视区域为参考,一般会配合带有滑动功能组件一起使用。

滑动屏幕内容,在可视区域上面显示出来,动态加载。

内容滑出可视区域,对应组件就会被销毁。

永远可以保证页面上数据只加载一部分,优化了页面数据加载,提高了性能。

限制条件

  1. LazyForEach必须在容器组件内使用,仅有List、Grid、Swiper、WaterFlow组件支持懒加载。
  2. cacheCount属性可以设置可视区域外面缓存的组件个数。
  3. LazyForEach在每次迭代中,必须创建且只允许创建一个子组件。
  4. 循环的时候,必须给循环的元素新增key,并且是唯一的key。如果key相同,很多时候都会遇到加载失败的情况。

页面语法

private data:MyDataSource=new MyDataSource()

List(){
  LazyForEach(this.data,(item:string,index:number)=>{
  
  },(item:string)=>item)
}

数据约束

定义一个类,实现IDataSource接口。

只有实现这个接口类,才能作为LazyForEach循环需要的数据约束。

/**
 * 想用LazyForEach必须实现IDataSource接口
 */
class Class BasicDataSource implements IDataSource{
  // 存放监听器
  private listeners:DataChangeListener[]= []
  // 这个数据就是用于存放我们循环的数据
  private originDataArray:string[] = []

  // 计算一共多少条数据
  public totalCount():number{
    return 0
  }

  // 获取数据
  public getData(index:number):string{
    return this.originDataArray[index]
  }

  // 该方法为框架侧调用,为LazyForEach组件向其数据源处listener监听
  // originDataArray里面的数据会被监听
  // LazyForEach调用
  registerDataChangeListener(listener:DataChangeListener):void{
    if(this.listeners.indexOf(listener)<0){
      console.info('add listener')
    }
  }

  // 该方案为框架测调用,为对应的LazyForEach组件在数据源处去除listener监听
  unregisterDataChangeListener(listener:DataChangeListener):void{
    const pos=this.listeners.indexOf(listener)
    if(pos>=0){
      console.info('remove listener')
      this.listeners.splice(pos,1)
    }
  }

  // 通知LazyForEach组件需要重载所有子组件
  notifyDataReload():void{
    this.listeners.forEach(listener=>{
      listener.onDataReloaded()
    })
  }

  // 通知LazyForEach组件需要在index对应索引处添加子组件
  notifyDataAdd(index:number):void{
    this.listeners.forEach(listener=>{
      listener.onDataAdd(index)
    })
  }

  // 通知LazyFoeEach组件在index对应索引处数据有变化,需要重建该子组件
  notifyDataChange(index:num):void{
    this.listeners.forEach(listener=>{
      listener.onDataChange(index)
    })
  }

  // 通知LazyForEach组件需要在index对应索引处删除该子组件
  notifyDataDelete(index:number):void{
    this.listeners.forEach(listener=>{
      listener.onDataDelete(index)
    })
  }

  // 通知LazyForEach组件将from索引和to索引处的子组件进行交换
  notifyDataMove(from:number,to:number):void{
    this.listeners.forEach(listener=>{
      listener.onDataMove(form,to)
    })
  }
  
}

构造一个类,用于保存我们页面循环需要的数据,以及动态添加的数据

class MyDataSource extends BasicDataSource<string>{
  private dataArray:string[] = []

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

  public getDate(index:number):string{
    return this.dataArray[index]
  }

  // 给数据添加数据,指定位置
  public addData(index:number,data:string):void{
    this.dataArray.splice(index,0,data)
    this.notifyDataAdd(index)
  }
  // 给数组添加数据,默认放在最后
  public pushData(data:string):void{
    this.dataArray.push(data)
    this.notifyDataAdd(this.dataArray.length-1)
  }
  
  public pushAllData(data:string[]):void{
    for(let index=0;index<data.length;index++){
      this.pushData(data[index])
    }
  }

}

页面使用

private data:MyDataSource=new MyDataSource()

aboutToAppear(){
  const array:string[]=[]
  for(let index=0;index<10;index++){
    array.push(`harmoney${index}`)
  }
  this.data.pushAllData(array)
}

封装工具

export class BasicDataSource<T> implements IDataSource {
  // 存放数据监听器
  private listeners: DataChangeListener[] = []
  // 这个数组就是用于存放我们循环的数据
  private originDataArray: T[] = []

  // 计算一共有多少条数据
  public totalCount(): number {
    return 0
  }

  //获取数据
  public getData(index: number): T {
    return this.originDataArray[index]
  }

  // 该方法为框架调用,为LazyForEach组件向其数据源出添加listener监听
  // orginDataArray 里面数据都会被监听
  //LazyForEach调用
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      console.log('add listener')
      this.listeners.push(listener)
    }
  }

  // 该方法为框架调用,为对应的LazyForEach组件在数据源处去除listener监听
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener)
    if (pos >= 0) {
      console.log('remove listener');
      this.listeners.slice(pos, 1)
    }
  }

  // 通知LazyForEach组件需要重载所有子组件
  notifyDataReload(): void {
    this.listeners.forEach(listener=>{
      listener.onDataReloaded()
    })
  }

  // 通知LazyForEach组件需要在index对应索引处添加子组件
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener=>{
      listener.onDataAdd(index)
    })
  }

  // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该组件
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener=>{
      listener.onDataChange(index)
    })
  }

  // 通知LazyForEach组件需要在index对应索引处删除子组件
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener=>{
      listener.onDataDelete(index)
    })
  }

  // 通知LazyForEach组件将form索引和to索引处的子组件进行交换
  notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener=>{
      listener.onDataMove(from, to)
    })
  }
}

import { BasicDataSource } from "./BasicDataSource";

export class MyDataSource<T> extends BasicDataSource<T> {
  private dataArray: T[] = []

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

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

  // 给数组添加数据,指定位置
  public addData(index: number, data: T): void {
    this.dataArray.splice(index, 0, data)
    this.notifyDataAdd(index)
  }

  // 给数组添加数据,默认放在最后
  public pushData(data: T): void {
    this.dataArray.push(data)
    this.notifyDataAdd(this.dataArray.length - 1)
  }

  public pushAllData(data: T[]): void {
    for (let index = 0; index < data.length; index++) {
      this.pushData(data[index])
    }
  }
}

更多关于HarmonyOS鸿蒙Next中封装LazyForEach懒加载的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS鸿蒙Next中封装LazyForEach懒加载的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,LazyForEach 是一种用于懒加载列表数据的组件,适用于处理大量数据时优化性能。通过 LazyForEach,只有在列表项即将显示时才会创建对应的组件,从而减少内存占用和初始化开销。

使用 LazyForEach 的基本步骤如下:

  1. 准备数据源,通常是一个数组或列表。
  2. 实现 itemGenerator 方法,用于生成每个列表项的组件。
  3. LazyForEach 中绑定数据源和 itemGenerator

示例代码:

@Entry
@Component
struct MyComponent {
  private data: number[] = [1, 2, 3, 4, 5];

  build() {
    Column() {
      LazyForEach(this.data, (item: number) => {
        Text(`Item: ${item}`)
          .fontSize(20)
          .margin(10);
      });
    }
  }
}

通过这种方式,LazyForEach 可以高效地处理大量数据,提升应用性能。

回到顶部