鴻蒙HarmonyOS開發(fā)ArkUI中的LazyForEach和SwiftUI中的ForEach的區(qū)別
SwiftUI 提供了三種不同的機(jī)制來構(gòu)建一棵樹的動態(tài)部分着撩,F(xiàn)orEach就是其中之一枫浙。
ArkUI是鴻蒙的核心UI布局框架我磁,除了ForEach,它還提供了LazyForEach厌衔,便于高性能開發(fā)璧帝。
由于ForEach往往和List搭配使用,我們會關(guān)注ForEach里的view是不是懶加載的富寿,在SwiftUI中睬隶,只有ForEach,沒有公開資料描述ForEach加載方式页徐,在WWDC20-10031的材料中提到過:List里的內(nèi)容總是以懶加載方式存在的苏潜。
然而測試發(fā)現(xiàn),當(dāng)list里的數(shù)據(jù)到達(dá)100000條后变勇,初始化CPU占有率會達(dá)到100%恤左,此時(shí)頁面雖然顯示了,但是無法滑動搀绣,即無響應(yīng)狀態(tài)飞袋。
List {
ForEach(0..<100000){ I in
ChatView(id: i)
}
}
why is the swiftUI list not lazy (compared to lazyVStack)?
Bad performance of large SwiftUI lists on macOS
一種優(yōu)化方式是給 List 里的內(nèi)容加上固定高度,這樣使用ForEach時(shí)SwiftUI就不需要計(jì)算每一個(gè)內(nèi)容的高度了链患。
List {
ForEach(0..<100000){ I in
ChatView(id: i)
.frame(width: 500, height: 15, alignment: .leading)
}
}
此外授嘀,SwiftUI提供了LazyVStack和LazyHStack這兩個(gè)容器,放在這兩個(gè)容器中的內(nèi)容是懶加載的锣险。
相比SwiftUI,ArkUI中的LazyForEach無法實(shí)現(xiàn)以下場景:
1览闰、SwiftUI中芯肤,可以使用ForEach直接遍歷,可以通過$0獲取索引压鉴。
VStack() {
// 遍歷從1-10崖咨,并創(chuàng)建從1-10的文本組件
ForEach((1...10), id: \.self) {
Text("\($0)…")
}
}
2、可以直接對數(shù)組進(jìn)行forEach油吭,進(jìn)行遍歷:
let name = ["a","b","c","d"]
name.forEach {
switch $0 {
// 對name進(jìn)行遍歷击蹲,找到a
case let x where x.hasPrefix("a"):
print("\(x) is here")
default:
print("hi, \($0)")
}
}
SwiftUI和ArkUI中的LazyForEach使用差異如下:
1、自由控制遍歷的次數(shù)
在SwiftUI中婉宰,比如用數(shù)組的前一半數(shù)據(jù)繪制Text:
ForEach(0..<foo.count/2) { index in
Text(foo[index])
}
在ArkUI中歌豺,以下代碼報(bào)錯:Argument of type ‘boolean’ is not assignable to parameter of type ‘a(chǎn)ny[]’.
ForEach(0..<foo.count/2,
(item, index) => {
ListItem() {
Stack50View()
}
},
(item) => item.toString()
)
2、List和ForEach搭配使用靈活性
在SwiftUI中心包,List中可以提供多個(gè)數(shù)據(jù)源和ForEach組合类咧,比如在List中添加一組ForEach,添加一個(gè)Text后再添加一組ForEach:
List{
ForEach(items,id:\.self){ item in
Text(item)
}
Text("其他內(nèi)容")
ForEach(0..<10){ I in
Text("id:\(i)")
}
}
在ArkUI中,List中只能添加ListItem痕惋,以下代碼報(bào)錯:The ‘List’ component can have only the ListItem, Section and ListItemGroup child component.
List() {
Text()
ForEach(this.arr,
(item, index) => {
ListItem() {
Stack50View()
}
},
(item) => item.toString()
)
ForEach(this.arr,
(item, index) => {
ListItem() {
Stack50View()
}
},
(item) => item.toString()
)
}
其他
SwiftUI中 ForEach內(nèi)對數(shù)據(jù)增区宇、刪、改值戳、查不需要通知框架層议谷。
ArkUI中的LazyForEach需要告知框架層。