ReactNative长列表原理浅析

2022年4月15日 317点热度 0人点赞 0条评论

今天正好看到了一篇关于ReactNative文章,聚焦的是APP设计中司空见惯的列表数据展示问题。

ReactNative的列表组件从最初的ListView到后来的FlatList(官方推荐)本人作为亲历者也都实际使用在项目的开发中。

作为最初的ListView 组件性能很差,没有内存回收机制,翻一页内存就涨一点,再翻一页内存又再涨一点。前 5 页滚动非常流畅,到了第 10 页时开始感觉到卡顿了,到 50 页的时候就基本就滑不动了。卡顿的原因就是无限列表太吃内存了,手机的可使用内存不够了,卡顿就发生了。这也是 React Native 刚出来被吐槽最多的地方。

2017年,官方的第二代列表组件 FlatList 出来后,第一代列表组件 ListView 就被废弃了,这时候无限列表性能开始好起来了。FlatList 在 iOS 表现很好,但在 Android 低端机还是能感觉到卡顿。

在实际的工作中对于不固定高度的列表项,在快速滑动时也会出现短暂空白的情况(来自测试同学的吐槽),当然可以使用一个占位元素,但始终不是最好的解决办法。

后面接触到了开源社区推出的RecyclerListView,相对于官方FlatList有了更进一步的性能提升。

FlastList 和 RecyclerListView 的底层实现都是滚动组件 ScrollView。

ScrollView

ScrollView 是一个支持横向或竖向的滚动组件,几乎所有页面都会用到。

ScrollView 组件类似于 Web 中的 或 标签,浏览器中的页面之所以能上下滚动,就是因为 html 或 body 标签默认有一个 overflow-y: scroll 的属性,如果你把标签的属性设置为 overflow-y: hidden,页面就不能滚动了。

React Native 的 ScrollView 组件在 Android 的底层实现是 ScrollView 和 HorizontalScrollView,在 iOS 的底层实现是 UIScrollView。

使用 ScrollView 组件时,我们通常并不直接给 ScrollView 设置固定高度或宽度,而是给其父组件设置固定高度或宽度。

ScrollView适合用来显示数量不多的滚动元素。放置在ScrollView中的所有组件都会被渲染,哪怕有些组件因为内容太长被挤出了屏幕外。

FlatList

FlatList组件用于显示一个垂直的滚动列表,其中的元素之间结构近似而仅数据不同。

FlatList更适于长列表数据,且元素个数可以增删。和ScrollView不同的是,FlatList并不立即渲染所有元素,而是优先渲染屏幕上可见的元素。

FlatList 组件底层使用的是虚拟列表 VirtualizedList,VirtualizedList 底层组件使用的是 ScrollView 组件。因此 VirtualizedList 和 ScrollView 组件中的大部分属性,FlatList 组件也可以使用。

FlatList 性能比 ScrollView 好的原因是, FlatList 列表组件通过利用按需渲染机制减少了首次渲染的视图,利用空视图的占位机制回收了原有视图的内存.

官方推荐的优化配置

RecyclerListView

RecyclerListView 是开源社区提供的列表组件,它的底层实现和 FlatList 一样也是 ScrollView,它也要求开发必须将内容整体分割成一个个列表项。

在首次渲染时,RecyclerListView 只有首屏内容和用户即将看到的内容才会渲染,所以它的首次渲染速度很快。在滚动渲染时,只会渲染屏幕内的和屏幕附近 250 像素的内容,距离屏幕太远的内容是空的。

React Native 的 RecyclerListView 复用灵感来源于 Native 的可复用列表组件。

在 iOS 中,表单视图 UITableView,实际就是可以上下滚动、左右滚动的可复用列表组件,它可以通过复用唯一标识符 reuseIdentifier,标记表单中的复用单元 cell,实现单元 cell 的复用。

在 Android 上,动态列表 RecyclerView 在列表项视图滚出屏幕时,不会将其销毁,相反会把滚动到屏幕外的元素,复用到滚动到屏幕内的新的列表项上。这种复用方法可以显著提高性能,改善应用响应能力,并降低功耗。

RecyclerListView 的复用机制是这样的,你可以把列表比作数组 list,把列表项类比成数组的元素。用户移动 ScrollView 时,相当于往数组 list 后面 push 新的元素对象,而 RecyclerListView 相当于把 list 的第一项挪到了最后一项中。挪动对象位置用到的计算资源少,也不用在内存中开辟一个新的空间。而创建新的对象,占用计算资源多,同时占用新的内存空间。

对比

从底层原理看:

  • ScrollView 内容的布局方式是从上到下依次排列的,你给多少内容 ScrollView 就会渲染多少内容;
  • FlatList 内容的布局方式还是从上到下依次排列,它通过更新第一个和最后一个列表项的索引控制渲染区域,默认渲染当前屏幕和上下 10 屏幕高度的内容,其他地方用空白视图进行占位;
  • RecyclerListView 性能最好,你应该优先使用它,但使用它的前提是列表项类型可枚举且高度确定或大致确定。

从使用场景上看:

  • ScrollView 适合内容少的页面,只有几个屏幕高页面是适合的;
  • FlatList 性能还过得去,但我不推荐你优先使用它,只有在你的列表项内容高度不可事先确定或者不可枚举的情况下使用它;
  • RecyclerListView 性能最好,你应该优先使用它,但使用它的前提是可枚举且高度确定或大致确定。

资源

1.滚动视图

https://reactnative.cn/docs/using-a-scrollview

2.RecyclerListView

https://github.com/Flipkart/recyclerlistview

40400ReactNative长列表原理浅析

这个人很懒,什么都没留下

文章评论