针对长列表加载这一场景,总共有如下五种优化手段。本实例使用前四种手段,通过这些优化手段的单个使用或组合使用,可以对列表渲染时间、页面滑动帧率、应用内存占用等方面带来优化,提升性能和用户体验:
- 懒加载:提供列表数据按需加载能力,解决一次性加载长列表数据耗时长、占用过多资源的问题,可以提升页面响应速度。
- 缓存列表项:提供屏幕可视区域外列表项长度的自定义调节能力,配合懒加载设置可缓存列表项参数,通过预加载数据提升列表滑动体验。
- 动态预加载:根据历史任务加载耗时情况,动态调整屏幕可视区域外数据预取数量,配合懒加载设置,可在列表不断滑动时,屏幕可视区外实时更新列表数据,通过预取和预渲染数据提升列表滑动体验。
- 组件复用:提供可复用组件对象的缓存资源池,通过重复使用已经创建过并缓存的组件对象,降低相同组件短时间内频繁创建和销毁的开销,提升组件渲染效率。
- 布局优化:使用扁平化布局方案,减少视图嵌套层级和组件数,避免过度绘制,提升页面渲染效率。
1、使用懒加载、缓存列表项、动态预加载和组件复用来优化列表加载性能
若开发者的应用中存在以下场景,并成为UI线程的帧率瓶颈,应该考虑使用组件复用机制提升应用性能:
- 滑动场景下对同一类自定义组件的实例进行频繁的创建与销毁。
- 反复切换条件渲染的控制分支,且控制分支中的组件子树结构比较复杂。
组件复用生效的条件是:
- 自定义组件被@Reusable装饰器修饰,即表示其具备组件复用的能力。
- 在一个自定义组件(父)下创建出来的具备组件复用能力的自定义组件(子),在可复用自定义组件从组件树上移除之后,会被加入到其父自定义组件的可复用组件缓存中。
- 在一个自定义组件(父)下创建可复用的子组件时,若可复用子节点缓存中有对应类型的可复用子组件的实例,会通过更新可复用子组件的方式,快速创建可复用子组件。
List({ scroller: this.menuScroller,space:0 }) {
LazyForEach(this.menuData, (item: ProductListBean, index: number) => {
ListItem() {
MenuCompotent({ menuData: item})//这里的组件复用是指组件数不频繁的创建customerOrder和RenderOrder,放到组件缓存区拿过来复用,节省了组件的创建时间,提高性能
.reuseId((item.timeDiscountInfo && item.timeDiscountInfo.name) ? 'isText' : 'noText')//组件结构根据if语句有变动,加入reuserId为结构创建ID提高复用效率,增加性能
.onClick(() => {
if (this.selectIndex != index) {
let oleSelectIndex = this.selectIndex
this.selectIndex = index
this.menudata?.changeSelected(oleSelectIndex, this.selectIndex)
this.onMenuSelected(this.selectIndex)
}
this.productScroller.scrollToIndex(index)
})
}
},(item: ProductListBean, index: number)=> JSON.stringify(item)+index)
ListItem().height(100)
}
.cachedCount(5)
2、MenuCompotent的组件复用
组件复用机制如下:
- 标记为@Reusable的组件从组件树上被移除时,组件和其对应的JSView对象都会被放入复用缓存中。
- 当列表滑动新的ListItem将要被显示,List组件树上需要新建节点时,将会从复用缓存中查找可复用的组件节点。
- 找到可复用节点并对其进行更新后添加到组件树中。从而节省了组件节点和JSView对象的创建时间。
@Component
@Reusable
export struct MenuComponent {
@Prop menuData: ProductMenuList
build() {
Text(this.menuData.ListName)
.height(34)
.width('100%')
.padding({ left: 8 })
}.width('100%').height('100%')
}
}
1.@Reusable:自定义组件被@Reusable装饰器修饰,即表示其具备组件复用的能力。
2.reuseId:用于标记自定义组件复用组,当组件回收复用时,复用框架将根据组件的reuseId来划分组件的复用组。如果只有一个复用的组件,可以不用设置reuseId。
性能收益
通过DevEco Studio的profiler工具分析复用前后的组件创建时间,可以得到应用使能组件复用后的优化情况,组件创建的时间平均从1800us降低到了570us。