React Native -- 高性能列表组件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React Native -- 高性能列表组件相关的知识,希望对你有一定的参考价值。

参考技术A 本章源码 FasterListDemo ,包括

如果之前没搭建过 RN 的开发环境可以先看 这里

高性能的简单列表组件,支持下面这些常用的功能:

如果需要分组/类/区(section),请使用 <SectionList> 。
一个最简单的例子:

具体的使用和属性参照 Demo 和 FlatList文档 吧,不做重复介绍

React-Native 0.50+ 新添加 SwipeableFlatList 组件,是在 FlatList 基础上添加了侧滑显示菜单的功能,类似于侧滑删除效果。

它有 FlatList 所有的属性和方法,另外它还有三个自己的属性:

2. maxSwipeDistance: number 或者 func, 必须要赋值,表示向左滑动的最大距离

3. renderQuickActions:func ,必须要赋值,表示滑动显示的内容

使用方法参照 本章Demo

之前 facebook 发布了高性能的列表组件 Flatlist (可理解为优化后的 Listview ),后来又增加了一个 SectionList 。属于增强版的Flatlist,支持头部悬浮等,如果你的列表不需要分组(section),那么可以使用结构更简单的<FlatList>。

React Native之FlatList组件(一)

参考技术A 在React Native0.43版本中引入了 FlatList , SectionList 与 VirtualizedList ,其中 VirtualizedList 是FlatList 与 SectionList 的底层实现。

经常使用ListView的同学都知道: ListView的性能是比较差的,尤其是当有大量的数据需要展示的时候,ListView对内存的占用是相当可观的、丢帧卡顿那是常有的事。

深入ListView的原理你会发现,ListView对列表中的Item是全量渲染的,并且没有复用机制,这就难以避免当让ListView渲染大数据量的时候会发生以下两个问题:

ListView的这种性能问题一直困扰着React Native开发者。有能力的公司、团队都纷纷对ListView做优化,封装自己的列表组件,然对性能的提升并不大,所以现在急需一个高性能的列表组件,于是便有了设计FlatList的构想;

FlatList是基于VirtualizedList的,要说FlatList的特性还要从VirtualizedList说起:

VirtualizedList 是FlatList 与 SectionList 的底层实现。Vritualization 通过维护一个有限的渲染窗口(其中包含可见的元素),并将渲染窗口之外的元素全部用合适的定长空白空间代替的方式,极大的改善了内存消耗以及在有大量数据情况下的使用性能。这个渲染窗口能响应滚动行为。当一个元素离可视区太远时,它就有一个较低优先级;否则就获得一个较高的优先级。渲染窗口通过这种方式逐步渲染其中的元素(在进行了任何交互之后),以尽量减少出现空白区域的可能性。

VirtualizedList有以下特性:

VirtualizedList除了简化API之外,新的列表组件还具有显着的性能增强,主要的是对于任意数量的行(Item)的增加不会带着内存的增加。 它主要是通过虚拟元素也就是在渲染窗口之外的元素将会被从组件结构上卸载以达到回收内存目的。这样会带来一个问题,即内部组件状态不会被保留,因此请确保你跟踪组件本身以外的任何重要状态,例如, 在Relay或Redux或Flux store。

限制渲染窗口还可以减少React和本地平台的工作量,例如View遍历。 即使你渲染了最后的一百万个元素,用这些新的列表也不需要渲染所有的元素来完成遍历。比如:你可以使用scrollToIndex跳至中间位置,而无需过多渲染。

另外VirtualizedList还对调度进行了一些改进,这对应用程序的响应很有帮助。 在任何手势或动画或其他交互完成后,呈现在窗口边缘的Item不会被频繁的渲染,并且渲染优先级比较低。

了解完 VirtualizedList 之后,接下来就让我们来认识一下FlatList的一些特性吧:

高性能的且使用简单的列表组件,支持一些特性:

如果需要分组/类/区(section)的功能,请使用 <SectionList> 。

FlatList组件实质是基于 <VirtualizedList> 组件的封装,因此除了 <VirtualizedList> 需要注意的事项之外还有下面这些需要注意的事项:

为了简化起见,data属性目前只支持普通数组。如果需要使用其他特殊数据结构,例如immutable数组,请直接使用更底层的VirtualizedList组件。

根据行数据data渲染每一行的组件。典型用法:

除data外还有第二个参数index可供使用。

如果设置了此选项,则会在列表头部添加一个标准的RefreshControl控件,以便实现“下拉刷新”的功能。同时你需要正确设置refreshing属性。

在等待加载新数据时将此属性设为true,列表就会显示出一个正在加载的符号。

设置为true则变为水平布局模式。

指定一开始渲染的元素数量,最好刚刚够填满一个屏幕,这样保证了用最短的时间给用户呈现可见的内容。注意这第一批次渲染的元素不会在滑动过程中被卸载,这样是为了保证用户执行返回顶部的操作时,不需要重新渲染首批元素。

此函数用于为给定的item生成一个不重复的key。Key的作用是使React能够区分同类元素的不同个体,以便在刷新时能够确定其变化的位置,减少重新渲染的开销。若不指定此函数,则默认抽取item.key作为key值。若item.key也不存在,则使用数组下标。

行与行之间的分隔线组件。不会出现在第一行之前和最后一行之后。�

通过它设置尾部组件

通过它设置头部组件

如果设置了多列布局(即将numColumns值设为大于1的整数),则可以额外指定此样式作用在每行容器上。

如果有除data以外的数据用在列表中(不论是用在renderItem还是Header或者Footer中),请在此属性中指定。同时此数据在修改时也需要先修改其引用地址(比如先复制到一个新的Object或者数组中),然后再修改其值,否则界面很可能不会刷新。

获取指定的Item;

用于获取总共有多少Item;

getItemLayout 是一个可选的优化,用于避免动态测量内容尺寸的开销,不过前提是你可以提前知道内容的高度。如果你的行高是固定的,getItemLayout用起来就既高效又简单,类似下面这样:

注意如果你指定了SeparatorComponent,请把分隔线的尺寸也考虑到offset的计算之中。

设置为true则使用旧的ListView的实现。

多列布局只能在非水平模式下使用,即必须是horizontal=false。此时组件内元素会从左到右从上到下按Z字形排列,类似启用了flexWrap的布局。组件内元素必须是等高的——暂时还无法支持瀑布流布局。

当列表被滚动到距离内容最底部不足onEndReachedThreshold的距离时调用。

决定当距离内容最底部还有多远时触发onEndReached回调。注意此参数是一个比值而非像素单位。比如,0.5表示距离内容最底部的距离为当前列表可见长度的一半时触发。

在可见行元素变化时调用。可见范围和变化频率等参数的配置请设置viewabilityconfig属性

可参考ViewabilityHelper的源码来了解具体的配置。

滚动到底部。如果不设置getItemLayout属性的话,可能会比较卡。

滚动到指定位置,如果不设置getItemLayout属性的话,可能会比较卡。

需要线性扫描数据 - 如果可能,请使用scrollToIndex。如果不设置getItemLayout属性的话只能滚动到当前渲染窗口的某个位置。

滚动到列表中的特定内容像素偏移量。

下面是一个较复杂的例子,其中演示了如何利用PureComponent来进一步优化性能和减少bug产生的可能:

以上是关于React Native -- 高性能列表组件的主要内容,如果未能解决你的问题,请参考以下文章

React Native组件生命周期

React Native 中 ScrollView 性能探究

react-native 一起来实现一个高性能循环滚动的轮播图吧!

React Native 桥接原生模块

记录React性能优化之“虚拟滚动”技术——react-window

React Native之FlatList组件(一)