此文章内容兼容API12,使用harmony next应用开发
概念解释
forEach 和 LazyForEach 都是应用于循环渲染,forEach 一般应用于数据量小,性能要求不高的场景;LazyForEach适用于数据量大,对性能要求较高的场景。
比较维度 | forEach | LazyForEach |
---|---|---|
数据源 | Array | IDataSource类型 |
渲染策略 | 一次性渲染所有的数据 | 只渲染可视区域的数据 |
内存 | 一次性加载所有的数据 | 只加载可视区域的数据,并且对划出可视区域的内容进行回收 |
数据监听 | 依赖于数组变化触发的UI更新 | 通过DataChangeListener来监听数据的变化,手动通知数据变动以刷新UI |
组件支持 | 无限制 | 只支持滚动容器组件,list、grid、swiper、waterFlow |
键值对 | 可选[默认键值对默认的键值生成函数,即(item: any, index: number) => { return index + ‘__’ + JSON.stringify(item) }] | 可选[默认键值对默认的键值生成函数,即(item: any, index: number) => { return viewId + ‘-’ + index.toString(); }] |
使用详解 - forEach
list.forEach((bean:xxxobject, index) => {})
使用详解 - LazyForEach
DataChangeListener接口:
interface DataChangeListener {
onDataReloaded(): void; // 重新加载数据完成后调用
onDataAdded(index: number): void; // 添加数据完成后调用
onDataMoved(from: number, to: number): void; // 数据移动起始位置与数据移动目标位置交换完成后调用
onDataDeleted(index: number): void; // 删除数据完成后调用
onDataChanged(index: number): void; // 改变数据完成后调用
onDataAdd(index: number): void; // 添加数据完成后调用
onDataMove(from: number, to: number): void; // 数据移动起始位置与数据移动目标位置交换完成后调用
onDataDelete(index: number): void; // 删除数据完成后调用
onDataChange(index: number): void; // 改变数据完成后调用
}
使用[很像安卓的Adapter]
class AdvDataSource implements IDataSource {
private listeners: DataChangeListener[] = [];
private list: CommonDetailBean[] = []
constructor(list: CommonDetailBean[]) {
this.list = list
}
totalCount(): number {
return this.list.length
}
getData(index: number): CommonDetailBean{
return this.list[index]
}
// 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
console.info('add listener');
this.listeners.push(listener);
}
}
// 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听
unregisterDataChangeListener(listener: DataChangeListener) {
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
console.info('remove listener');
this.listeners.splice(pos, 1);
}
}
resetData(list: CommonDetailBean[]) {
this.list = list;
this.notifyDataReload();
}
// 通知LazyForEach组件需要重载所有子组件
notifyDataReload(): void {
this.listeners.forEach(listener => {
listener.onDataReloaded();
})
}
}
@Component
{
@State private data: AdvDataSource = new AdvDataSource(this.advBeanArray)
LazyForEach(this.data, (item: CommonDetailBean, index: number) => {
Image(this.getImgUrl(item))
.width('100%')
.height('100%')
.alt($r('app.media.home_banner'))
}), (item: CommonDetailBean, index: number) => {
return JSON.stringify(item) + index;
}
}
问题
1,解决LazyForEach数据源变更后界面闪烁的问题:去除ForEach中的index参数
Repeat
官方推出新的渲染组件,Repeat,提供了两种模式non-virtualScroll模式和virtualScroll模式。
non-virtualScroll模式类似于ForEach的使用。渲染短数据列表、组件全部加载的场景
virtualScroll模式类似于LazyForEach的使用。渲染需要懒加载的长数据列表、通过组件复用优化性能表现的场景。需要创建模板代码,用于复用view。
Repeat:可复用的循环渲染-其他状态管理-状态管理(V2)-状态管理-学习ArkTS语言-基础入门 - 华为HarmonyOS开发者
Repeat