当前位置: 首页 > news >正文

实用指南:【鸿蒙面试题-6】LazyForEach 懒加载

1. 什么是LazyForEach?

LazyForEach是一个数据懒加载组件,主要用于在滚动容器中根据可视区域按需创建和销毁组件,以降低内存占用。它通过延迟加载数据,只在需要时才加载和渲染数据,从而优化性能,提升用户体验。

2. 为什么需要LazyForEach?

  • 减少内存占用:通过按需加载和销毁组件,减少内存占用,避免一次性加载大量数据导致的性能问题。
  • 提升性能:在长列表或瀑布流等场景中,LazyForEach可以显著减少页面首次加载时间和滑动时的卡顿。
  • .优化用户体验:通过减少加载时间,提升用户在使用应用时的流畅性和响应速度。

3. 如何使用LazyForEach?

1.在容器组件内使用:LazyForEach必须在容器组件(如List、Grid、Swiper、WaterFlow)内使用。

2.创建数据源:实现一个数据源类,继承自BasicDataSourceIDataSource接口,提供数据总量、获取数据、添加数据等方法。

3.使用LazyForEach:在组件中使用LazyForEach,传入数据源、子组件生成函数和键值生成函数。

4.处理数据变化:通过DataChangeListener对象处理数据变化,调用onDataAddonDataChange等方法通知LazyForEach更新。

// commons/basic/src/main/ets/utils/LazyForEachHelper.ets
export class LazyForEachDataSource implements IDataSource {
private listeners: DataChangeListener[] = [];
// 数据源
private dataArray: T[] = [];
// 返回数据的长度
public totalCount(): number {
return this.dataArray.length;
}
// 返回数组指定指定索引的数据
public getData(index: number) {
return this.dataArray[index];
}
// 给数组增加一条数据
public pushData(data: T): void {
this.dataArray.push(data);
this.notifyDataAdd(this.dataArray.length - 1);
}
// 批量设置数组
public setArray(arr: T[]) {
this.dataArray = arr
//   通知UI更新
this.notifyDataReload()
}
// 删除数组中的某一条数据
// 修改数组中某个数据 属性
// 数组中元素 调换位置
// 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) = 0) {
console.info('remove listener');
this.listeners.splice(pos, 1);
}
}
// 数据改变,  通知UI更新 所有数据
notifyDataReload(): void {
this.listeners.forEach(listener => {
listener.onDataReloaded();
})
}
// 添加数据了 顺便帮你更新
notifyDataAdd(index: number): void {
this.listeners.forEach(listener => {
listener.onDataAdd(index);
// 写法2:listener.onDatasetChange([{type: DataOperationType.ADD, index: index}]);
})
}
// 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件
notifyDataChange(index: number): void {
this.listeners.forEach(listener => {
listener.onDataChange(index);
// 写法2:listener.onDatasetChange([{type: DataOperationType.CHANGE, index: index}]);
})
}
// 通知LazyForEach组件需要在index对应索引处删除该子组件
notifyDataDelete(index: number): void {
this.listeners.forEach(listener => {
listener.onDataDelete(index);
// 写法2:listener.onDatasetChange([{type: DataOperationType.DELETE, index: index}]);
})
}
// 通知LazyForEach组件将from索引和to索引处的子组件进行交换
notifyDataMove(from: number, to: number): void {
this.listeners.forEach(listener => {
listener.onDataMove(from, to);
// 写法2:listener.onDatasetChange(
//         [{type: DataOperationType.EXCHANGE, index: {start: from, end: to}}]);
})
}
notifyDatasetChange(operations: DataOperation[]): void {
this.listeners.forEach(listener => {
listener.onDatasetChange(operations);
})
}
}
import { LazyForEachDataSource } from "./LazyForEach"
interface person {
id: number,
name: string,
age: number
}
@Entry
@Component
export struct Demo {
dataArray: person[] = [
{ id: 1, name: '张三', age: 18 },
{ id: 2, name: '李四', age: 19 },
{ id: 3, name: '王五', age: 20 },
{ id: 4, name: '赵六', age: 21 },
{ id: 5, name: '孙七', age: 22 },
{ id: 6, name: '周八', age: 23 },
{ id: 7, name: '吴九', age: 24 },
{ id: 8, name: '郑十', age: 25 },
{ id: 9, name: '钱十一', age: 26 },
{ id: 10, name: '王十二', age: 27 },
{ id: 11, name: '冯十三', age: 28 },
{ id: 12, name: '陈十四', age: 29 },
{ id: 13, name: '褚十五', age: 30 },
{ id: 14, name: '卫十六', age: 31 },
{ id: 15, name: '蒋十七', age: 32 },
{ id: 16, name: '沈十八', age: 33 },
{ id: 17, name: '韩十九', age: 34 },
{ id: 18, name: '杨二十', age: 35 },
{ id: 19, name: '朱二十一', age: 36 },
{ id: 20, name: '秦二十二', age: 37 }
];
lazyData: LazyForEachDataSource = new LazyForEachDataSource()
aboutToAppear(): void {
this.lazyData.setArray(this.dataArray);
}
build() {
Column() {
List({space:10}) {
LazyForEach(this.lazyData, (item: person, index: number) => {
ListItem() {
Text(`我叫${item.name}我今年${item.age}岁`).width('100%').height(50).backgroundColor(Color.White).textAlign(TextAlign.Center)
}
}, (item: person) => item.id.toString()) // 使用id作为key
}
}.width("100%").height("100%").backgroundColor(Color.Pink)
}
}

总结

  1. LazyForEach 接收数据源 不再是普通的数组, 而是一个 继承了IDataSource接口的实例
  2. 真正数据/数组 存放在 实例的成员上
  3. 除此之外还重要,还有很重要的成员 - 数据变化监听器 DataChangeListener
  4. 要操作数据的时候 直接操作真正的数据源 -> 主动调用 数据变化监听器的一些方法(add/delete/move)
  5. 注意第三个参数要传入唯一标识的 id ,内部使用 diff 算法时才可以实现增量更新而不是全量更新
http://www.jsqmd.com/news/545/

相关文章:

  • 基于LlamaIndex的相似性搜索
  • 第二周预习报告(AI)
  • 编写代码时遇到的checkstyle问题归纳
  • .netcore的Lucene.Net基础应用
  • rook-ceph CRD资源配置时效困难
  • 实用指南:conda常见问题
  • 关于1200模拟量输入滤波的问题
  • 在Ubuntu 16.04上安装openjdk-6/7/8-jdk的步骤
  • 物流行业信息咨询智能问答系统
  • yoloV8
  • 插座(SOCKET)
  • 线性代数 行列式 | 子式 / 主子式 / 顺序主子式 / 余子式 / 代数余子式 - 教程
  • Red Hat 8.5.0-18 部署ceph文件系统 - 实践
  • kettle从入门到精通 第108课 ETL之kettle 国产麒麟系统安装kettle教程
  • 部署 Squid 代理服务
  • k8s--etcd - 详解
  • HBase 的自带命令行工具 hbase shell 的基本使用
  • 市场交易反心理特征之一:太过完美而不敢买入
  • 3peak DCDC转换芯片选型列表
  • 重塑公司绩效管理的 6 种方法
  • 详细介绍:从“下山”到AI引擎:全面理解梯度下降(上)
  • flask下的MySQL增删改查
  • tips图解数组名与指针的关系
  • Confluent-Kafka-go 发布超过 1M 消息失败困难克服
  • mysql查看数据库大小,可以通过查询系统表来实现
  • TPP21206替代MPQ8633,12A电流同步降压DCDC
  • 组件重新装载时 useSWR 会发起请求
  • kettle插件-kettle数据清洗插件,轻松处理脏数据
  • Java 如何在 Excel 中添加超链接?使用 Spire.XLS for Java 轻松实现 - 教程
  • 中二