LazyForEach从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。当在滚动容器中使用了LazyForEach,框架会根据滚动容器可视区域按需创建组件,当组件滑出可视区域外时,框架会进行组件销毁回收以降低内存占用。
👇🏻👇🏻👇🏻求关注👇🏻👇🏻👇🏻
public class DataChangeListener <: RemoteData {
func onDataReloaded(): Unit
func onDataAdd(index: Int64): Unit
func onDataDelete(index: Int64): Unit
func onDataChange(index: Int64): Unit
func onDataMove(fromIdx: Int64, toIdx: Int64): Unit
}
构造函数
init(IDataSource, (T, Int64) -> Unit,(T, Int64) -> String)
public init(dataSource: IDataSource<T>, itemGeneratorFunc!: (T, Int64) -> Unit, keyGeneratorFunc!: (T, Int64) -> String)
构建一个LazyForEach对象。
参数名 | 参数类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
dataSource | IDataSource | 是 | - | LazyForEach数据源,需要开发者实现相关接口。 |
itemGeneratorFunc | (T, Int64) -> Unit | 是 | - | 子组件生成函数,为数组中的每一个数据项创建一个子组件。lambda函数的第一个泛型参数为数据类型,必须为FFIData的子类;第二个参数为当前列表项的索引值。 |
keyGeneratorFunc | (T, Int64) -> String | 否 | - | 匿名函数,用于键值生成,为给定数组项生成唯一且稳定的键值。当子项在数组中的位置更改时,子项的键值不得更改,当数组中的子项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则LazyForEach中的所有节点都将重建。 |
自定义类型说明
IDataSource
public interface IDataSource<T> {
func totalCount(): Int64
func getData(index: Int64): T
func onRegisterDataChangeListener(listener: DataChangeListener): Unit
func onUnregisterDataChangeListener(listener: DataChangeListener): Unit
}
函数
totalCount()
public func totalCount(): Int64
获得数据总数。
getData(Int64)
public func getData(index: Int64): T
获取索引值index对应的数据。
参数名 | 参数类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
index | Int64 | 是 | - | 对应的索引值。 |
onRegisterDataChangeListener(DataChangeListener)
public func onRegisterDataChangeListener(listener: DataChangeListener): Unit
注册数据改变的监听器
参数名 | 参数类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
listener | DataChangeListener | 是 | - | 数据变化监听器。 |
onUnregisterDataChangeListener(DataChangeListener)
public func onUnregisterDataChangeListener(listener: DataChangeListener): Unit
注销数据改变的监听器。
参数名 | 参数类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
listener | DataChangeListener | 是 | - | 数据变化监听器。 |
DataChangeListener
public class DataChangeListener {
public init(id: Int64)
public func onDataReloaded(): Unit
public func onDataAdd(index: Int64): Unit
public func onDataDelete(index: Int64): Unit
public func onDataChange(index: Int64): Unit
public func onDataMove(fromIdx: Int64, toIdx: Int64): Unit
}
数据变化监听器类型。
构造函数
init(Int64)
public init(id: Int64)
创建一个DataChangeListener类型的对象。
函数
onDataReloaded()
public func onDataReloaded(): Unit
通知组件重新加载所有数据。键值没有变化的数据项会使用原先的子组件,键值发生变化的会重建子组件。
onDataAdd(Int64)
public func onDataAdd(index: Int64): Unit
通知组件index的位置有数据添加。
参数名 | 参数类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
index | Int64 | 是 | - | 数据添加位置的索引值。 |
onDataDelete(Int64)
public func onDataDelete(index: Int64): Unit
通知组件删除index位置的数据并刷新LazyForEach的展示内容。
参数名 | 参数类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
index | Int64 | 是 | - | 数据删除位置的索引值。 |
onDataChange(Int64)
public func onDataChange(index: Int64): Unit
通知组件index的位置有数据有变化。
参数名 | 参数类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
index | Int64 | 是 | - | 数据变化位置的索引值。 |
onDataMove(Int64, Int64)
public func onDataMove(fromIdx: Int64, toIdx: Int64): Unit
通知组件数据有移动。
参数名 | 参数类型 | 必填 | 默认值 | 描述 |
---|---|---|---|---|
fromIdx | Int64 | 是 | - | 数据移动起始位置。 |
toIdx | Int64 | 是 | - | 数据移动目标位置。 |
使用限制
- 数据懒加载必须在容器组件内使用,且仅有List、Grid以及Swiper组件支持数据的懒加载(即只加载可视部分以及其前后少量数据用于缓冲),其他组件仍然是一次加载所有的数据。
- LazyForEach在每次迭代中,必须且只允许创建一个子组件。
- 生成的子组件必须允许在LazyForEach的父容器组件中。
- 允许LazyForEach包含在if/else条件渲染语句中,也允许LazyForEach中出现if/else条件渲染语句。
- 键值生成器必须针对每个数据生成唯一的值,如果键值相同,将导致键值相同的UI组件渲染出现问题。
- LazyForEach必须使用DataChangeListener对象来进行更新,第一个参数dataSource使用状态变量时,状态变量改变不会触发LazyForEach的UI刷新。
- 为了高性能渲染,通过DataChangeListener对象的onDataChange方法来更新UI时,需要生成不同于原来的键值来触发组件刷新。
- List使用LazyForEach加载子组件时,没有设置List的宽高,会加载所有子组件,设置了List的宽高,会加载List显示区域内的子组件。
示例代码
import ohos.base.*
import ohos.component.*
import ohos.state_manage.*
import ohos.state_macro_manage.*
import std.collection.*
public class Student {
public Student(
let name: String,
let id: Int64
) {}
}
class StudentDataSource <: IDataSource<Student> {
public StudentDataSource(let data_: ArrayList<Student>) {}
public var listenerOp: Option<DataChangeListener> = None
public func totalCount(): Int64 {
return data_.size
}
public func getData(index: Int64): Student {
return data_[index]
}
public func onRegisterDataChangeListener(listener: DataChangeListener): Unit {
listenerOp = listener
}
public func onUnregisterDataChangeListener(listener: DataChangeListener): Unit {
listenerOp = None
}
public func notifyChange(): Unit {
let listener: DataChangeListener = listenerOp.getOrThrow()
listener.onDataReloaded()
}
}
func getDS(): StudentDataSource
{
let data: ArrayList<Student> = ArrayList<Student>()
for (i in 0..50) {
data.append(Student("name ${i}", i * i))
}
let dataSourceStu: StudentDataSource = StudentDataSource(data)
return dataSourceStu
}
let dataSourceStu: StudentDataSource = getDS()
var changeID: Int64 = 0
@Entry
@Component
public class MyView {
public func build(): Unit {
Column(30) {
Text("-----------------")
Column {
LazyForEach(dataSourceStu, itemGeneratorFunc: {stu: Student, idx: Int64 =>
Column {
Text(stu.name)
}
})
}
.height(400.0)
Text("click to notifyChange").onClick({ evt =>
dataSourceStu.data_.remove(changeID)
dataSourceStu.data_.insert(changeID, Student("xiaoming", 10086))
dataSourceStu.notifyChange()
changeID += 1
})
}
}
}
如对您有帮助,帮忙点个“在看 、关注” 让更多的人受益~!
技术交流群可加wx“LB-9191”备注cangjie