前言
长列表或者无限下拉列表是最常见的应用场景之一。React Native在0.43版本之前写列表需要使用ListView,ListView存在性能问题,API也不友好,所以官方在0.43版本推出了FlatList,有如下优点:
- API更加友好和丰富;
- 性能好很多;
使用方法
ListView
对于ListView
最重要的两个属性,一个是数据源(dataSource),再一个就是列表项渲染(renderRow)。ListView
可以根据不同的数据结构对应的生成普通长列表和分组长列表。
普通长列表
普通长列表使用cloneWithRows(dataBlob, rowIdentities)
创建datasource,在项目中dataBlob
的数据结构如下:
[
{id:1},
{name:'Mark'},
...
]
在使用renderRow(rowData, sectionID, rowID, highlightRow)
渲染列表项的时候,rowData
就是数组中每一个对象。
FlatList
特别注意:
renderItem={this._rowRenderer}
如果没做手动指定传入的实参,接收时
_rowRenderer = ({ item, index }) => { };
第一个参数一点要用item接收,否则接收的属性变量都是undefined
RecyclerListView
对比
对比 | ListView | FlatList |
---|---|---|
1000条时内存 | 350M | 180M |
2000条时内存 | / | 230M |
js-fps | 4~6 fps | 8~20 fps |
js-pfs
类似于游戏的画面渲染的帧率,60 为最高。它用于判断 js 线程的繁忙程度,数值越大说明 js 线程运行状态越好,数值越小说明 js 线程运行状态越差。在快速滑动测试 ListView 的时候, js-pfs
的值一直在 4~6 范围波动,即使停止滑动,js-pfs
的值也不能很快恢复正常。而 FlatList 在快速滚动后停止,js-pfs
能够很快的恢复到正常。
内存方面,ListView 滑动到 1000 条时,已经涨到 350M。这时机器已经卡的不行了,所以没法滑到 2000 条并给出相关数据。而 FlatList 滑到 2000 条时的内存,也比 ListView 1000 条时的内存少不少。说明,FlatList 对内存的控制是很优秀的。
主观体验方面:FlatList 快速滑动至 2000 条的过程中全程体验流畅,没有出现卡顿或肉眼可见的掉帧现象。而ListView 滑动到 200 条开始卡顿,页面滑动变得不顺畅,到 500 条渲染极其缓慢,到 1000 条时已经滑不动了。
但即使是 React Native 官方支持的性能最好FlatList
组件,在Android的一些机型上的表现也差强人意,特别是使用超过两年的Android手机,基本上就是到非常卡的状态了。
FlatList的原理
- 将列表不可视区域内的视图,进行回收,并从内存中清除,下次需要时在重新创建
- 这就需要在设备滚动时,能快速创建需要的视图,才能保证列表流畅的展示给用户
- 视图的创建是非常昂贵的,并伴随着内存的消耗,这也就意味着FlatList或导致大量的视图重新创建以及垃圾回收
RecyclerListView
受到 Android RecyclerView
和 iOS UICollectionView
的启发
- 仅创建可见区域的视图,这步与
FlatList
是一致的。 cell recycling
,重用单元格- RecyclerListView 通过对不可见视图对象进行缓存及重复利用,一方面不会创建大量的视图对象,另一方面也不需要频繁的创建视图对象和垃圾回收。
RecyclerListView的滚动帧率是远大于FlatList的。FlatList在滚动时帧率波动比较严重,上手体验会发现比较卡顿且较多白屏现象。相对来说,RecyclerListView 的帧率变化相对稳定,基本都能维持到 35fps 以上,平均值在46fps 左右。