一、数据加载方式
在之前的文章里,我已经向大家介绍了一种循环渲染数据的方式(《跟我一起学“Harmony-ArkTS”——页面元素渲染》),就是ForEach,ForEach加载数据的特点就是,如果列表数据较少,数据一次性全量加载不是性能瓶颈,可以使用ForEach一次性加载全量数据。
可如果有上万条数据,一次性加载上万条数据,必然会造成性能问题,同时,我们是否有必要在当前时刻一次性加载上万条数据呢?如何解决这些问题,这个时候,我们就引出了今天的主角:懒加载——LazyForEach了。
LazyForEach实现了按需加载,针对列表数据量大、列表组件复杂的场景,减少了页面首次启动时一次性加载数据的时间消耗,减少了内存峰值。
简单的理论介绍完了,如何使用LazyForEach呢,咱们接着往下看。
在使用方面,LazyForEach与ForEach不同点在于,ForEach里所接收的数据源类型可以是任意的,而LazyForEach里所接收的数据源类型,必须是实现了IDataSource接口的类型。
因此,案例代码如下:
/**
* 实现IDataSource接口
*/
class BasicDataSource implements IDataSource {
/**
* 监听器
*/
private listeners: DataChangeListener[] = [];
/**
* 这里应该是来自后端给的数据列表
* 本文章举例子为了简单实现就用了简单数据
*/
private originDataArray: Array<string> = [
'你好鸿蒙',
'你好鸿蒙',
'你好鸿蒙',
'你好鸿蒙',
'你好鸿蒙',
'你好鸿蒙',
'你好鸿蒙',
'你好鸿蒙',
'你好鸿蒙',
'你好鸿蒙',
'你好鸿蒙',
'你好鸿蒙',
];
/**
* 获取总数
*
* @returns 总数
*/
public totalCount(): number {
return this.originDataArray.length;
}
/**
* 获取指定位置的数据
* 注意:这里函数的返回类型应该与后端返回数据列表的数据类型一致
*
* @param index 索引
* @returns 指定位置的数据
*/
public getData(index: number): string {
return this.originDataArray[index];
}
/**
* 为LazyForEach组件向其数据源处添加listener监听
*
* @param listener 监听器
*/
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
console.info('add listener');
this.listeners.push(listener);
}
}
/**
* 为对应的LazyForEach组件在数据源处去除监听器
*
* @param listener 监听器
*/
unregisterDataChangeListener(listener: DataChangeListener): void {
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
console.info('remove listener');
this.listeners.splice(pos, 1);
}
}
/**
* 重新加载所有组件
*/
onDataReloaded(): void {
this.listeners.forEach(listener => {
listener.onDataReloaded();
})
}
/**
* 在指定位置添加子组件
*
* @param index 索引
*/
notifyDataAdd(index: number): void {
this.listeners.forEach(listener => {
listener.onDataAdd(index);
})
}
/**
* 指定位置重新加载子组件
*
* @param index 索引
*/
notifyDataChange(index: number): void {
this.listeners.forEach(listener => {
listener.onDataChange(index);
})
}
/**
* 指定位置删除子组件
*
* @param index 索引
*/
notifyDataDelete(index: number): void {
this.listeners.forEach(listener => {
listener.onDataDelete(index);
})
}
/**
* 将指定位置的组件交换
*
* @param from 原索引
* @param to 目标索引
*/
notifyDataMove(from: number, to: number): void {
this.listeners.forEach(listener => {
listener.onDataMove(from, to);
})
}
}
@Entry
@Component
struct LazyForEachPage {
private title: string = '懒加载案例';
private data: BasicDataSource = new BasicDataSource();
build() {
Column({ space: 50 }) {
Text(this.title)
.fontSize(20)
.fontWeight(FontWeight.Bold)
List({ space: 20 }) {
LazyForEach(this.data, (item: string, index: number) => {
ListItem() {
Text(index + 1 + ':' + item)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Pink)
}
.width('100%')
})
}
.alignListItem(ListItemAlign.Center)
.height('30%')
.width('100%')
.backgroundColor(Color.Gray)
}
}
}
基础代码虽然出来了,但是这里面其实还遗留了一个小问题。目前我们的模拟数据偏少也偏简单,当数据稍微多点稍微偏复杂了以后,用户滑动到列表最底端时,在快速下滑,可能会引起“滑动白块”的现象。这是因为用户上一次只请求了可视区上的3条数据,如果滑动速度过快,后导致数据来不及加载而出现白块,会给用户带来糟糕的体验。那么怎么解决这个问题呢?您且听我娓娓道来。
为了解决“滑动白块”问题,我们可以为懒加载添加缓存列表项。LazyForEach可以通过设置cacheCount来指定缓存数量,在设置缓存cacheCount后,除可视区内显示的ListItem组件外,还会预先将可视区外指定数量的列表项数据缓存。这样当一个可视区数据加载完成后,再次向下滑动,会先加载上一次请求的数据,加载完后,在加载本次请求的数据,进而解决“滑动白块”的问题。
案例代码如下:
@Entry
@Component
struct LazyForEachPage {
private title: string = '懒加载案例';
private data: BasicDataSource = new BasicDataSource();
build() {
Column({ space: 50 }) {
Text(this.title)
.fontSize(20)
.fontWeight(FontWeight.Bold)
List({ space: 20 }) {
LazyForEach(this.data, (item: string, index: number) => {
ListItem() {
Text(index + 1 + ':' + item)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Pink)
}
.width('100%')
})
}
.alignListItem(ListItemAlign.Center)
.cachedCount(3) // 设置缓冲区配置
.height('30%')
.width('100%')
.backgroundColor(Color.Gray)
Button('返回')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.onClick(() => {
router.back();
})
}
}
}
只需在List组件上配置cacheCount属性即可。
以上就是懒加载的使用方法,更多关于LazyForEach使用方法的内容,大家可以参考LazyForEach官方文档进行深入学习。
二、小结
本章言简意赅的为大家介绍了懒加载(LazyForEach),下一章,为大家介绍视频组件和二维码组件的内容。最后,创作不易,如果大家觉得我的文章对学习鸿蒙有帮助的话,就动动小手,点个免费的赞吧!收到的赞越多,我的创作动力也会越大哦,谢谢大家🌹🌹🌹!!!