javascript 大列表的 React-Native FlatList 性能问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47678959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React-Native FlatList performance problems with large list
提问by bucsy
My code gets Json data to an array lists the data using a FlatList. It looks like a phonebook photo and text in a row.
我的代码将 Json 数据获取到一个数组,使用FlatList. 它看起来像一排电话簿照片和文字。
Here is My code:
这是我的代码:
renderItem = ({ item }) =>
(
<ListItem
title={item.username}
avatar={{ uri: item.photo }}
/>
)
render() {
console.log(this.state.myData);
return (
<View style={styles.container}>
<FlatList
data={this.state.myData}
renderItem={this.renderItem}
/>
</View>
);
}
Its works and I get the output, but the performance is slow. Rendering takes approximately 10 seconds which is annoying to the user. What should I do to make it faster?
它的工作原理,我得到了输出,但性能很慢。渲染大约需要 10 秒,这对用户来说很烦人。我该怎么做才能让它更快?
回答by Filipe Merker
Edit Dec 20 '19: The information on this answer became part of the official docs. You should check it out!
19 年 12 月 20 日编辑:有关此答案的信息已成为官方文档的一部分。你应该检查一下!
Edit May 26 '18: This answer became a bigger and more complete post on github
18 年 5 月 26 日编辑:这个答案在 github 上变成了一个更大更完整的帖子
If you follow this thread, you'll see that react's team is already aware of this performance issue.
如果你关注这个线程,你会看到 React 的团队已经意识到这个性能问题。
There is no silver bullet for this issue, you have to consider the trade offs of every approach and what you think is a good experience for your audience. But fortunately there are several tweaks you can try and improve your FlatList.
这个问题没有灵丹妙药,您必须考虑每种方法的权衡以及您认为对观众来说是一种很好的体验。但幸运的是,您可以尝试进行一些调整并改进您的FlatList.
Terms and meanings
术语和含义
There are a lot of terms used (on docsor some issues) that were confusing for me at first. So, let's get this out of the way from the start.
有很多术语(在文档或某些问题上)起初让我感到困惑。所以,让我们从一开始就解决这个问题。
VirtualizedListis the component behind
FlatList, and is React Native's implementation of the 'virtual list' concept.Performance, in this context, imply a smooth (not choppy) scroll (and navigation in or out of your list) experience.
- Memory consumption, in this context, is how much information about your list is being stored in memory, which could lead to a app crash.
- Blank areasmeans that the VirtualizedList couldn't render your items fast enough, so you enter on a part of your list with non rendered components.
- Windowhere is not your viewport but rather, size of the area in which items should be rendered.
VirtualizedList是 背后的组件
FlatList,是 React Native 对“虚拟列表”概念的实现。在这种情况下,性能意味着平滑(而不是断断续续)滚动(以及导航进出列表)体验。
- 在这种情况下,内存消耗是指在内存中存储了多少有关您的列表的信息,这可能会导致应用程序崩溃。
- 空白区域意味着 VirtualizedList 无法足够快地呈现您的项目,因此您使用未呈现的组件输入列表的一部分。
- 此处的窗口不是您的视口,而是应呈现项目的区域的大小。
Props
道具
One way to improve your FlatListis by tweaking it's props. Here are a list of props that can help your with that.
改善你的一种方法FlatList是调整它的道具。这里有一个道具列表,可以帮助你做到这一点。
removeClippedSubviews
删除剪辑子视图
You can set the removeClippedSubviewsprop to true, which unmount components that are off of the window.
您可以将removeClippedSubviewsprop设置为 true,这会卸载窗口外的组件。
Win:This is very memory friendly, as you will always have a little rendered list.
Win:这对内存非常友好,因为你总会有一个小的渲染列表。
Trade offs:Be aware, that this implementation can have bugs, such as missing content if you use it on a component that will not unmount (such as a navigation route). It also can be less performant, having choppy scroll animations for big lists with complex items on not-so-good devices, as it make crazy amounts of calculations per scroll.
权衡:请注意,如果您在不会卸载的组件(例如导航路线)上使用此实现,则此实现可能存在错误,例如丢失内容。它也可能性能较差,在不太好的设备上为包含复杂项目的大列表提供断断续续的滚动动画,因为它每次滚动都会进行大量的计算。
maxToRenderPerBatch
maxToRenderPerBatch
You can set the maxToRenderPerBatch={number}, which is a VirtualizedListprop that can be passed directly to FlatList. With this, you can control the amount of items rendered per batch, which is the next chunk of items rendered on every scroll.
您可以设置maxToRenderPerBatch={number},这是一个VirtualizedList可以直接传递给FlatList. 有了这个,您可以控制每批渲染的项目数量,这是在每次滚动时渲染的下一个项目块。
Win:Setting a bigger number means less visual blank areas when scrolling (a better the fill rate).
赢:设置更大的数字意味着滚动时更少的视觉空白区域(更好的填充率)。
Trade offs:More items per batch means less JavaScript performance, which means less responsiveness (clicking a item and opening the detail). If you have a static and non-interactive list, this could be the way to go.
权衡:每批次更多的项目意味着 JavaScript 性能下降,这意味着响应能力下降(单击项目并打开详细信息)。如果您有一个静态和非交互式列表,这可能是要走的路。
initialNumToRender
初始数量到渲染
You can set the initialNumToRender={number}. This means the initial amount of items to render.
您可以设置initialNumToRender={number}. 这意味着要渲染的初始项目数量。
Win:You can set this value to the precise number of items that would cover the screen for every device. This can be a big performance boost when rendering the list component.
Win:您可以将此值设置为覆盖每个设备屏幕的精确项目数。在渲染列表组件时,这可以极大地提升性能。
Trade offs:You are most likely to see blank areas when setting a low initialNumToRender.
权衡:设置低initialNumToRender.
windowSize
窗口大小
You can set the windowSize={number}. The number passed here is a measurement unit where 1 is equivalent to your viewport height. The default value is 21, being 10 viewports above, 10 below, and one in between.
您可以设置windowSize={number}. 此处传递的数字是一个测量单位,其中 1 相当于您的视口高度。默认值为 21,即上方 10 个视口、下方 10 个视口和中间 1 个视口。
Win:If you're worried mainly about performance, you can set a bigger windowSizeso your list will run smoothly and with less blank space. If you're mainly worried about memory consumption, you can set a lower windowSizeso your rendered list will be smaller.
Win:如果您主要担心性能,您可以设置更大的值,windowSize这样您的列表将运行顺畅且空白空间更少。如果您主要担心内存消耗,您可以设置一个较低的值,windowSize这样您的渲染列表就会更小。
Trade offs:For a bigger windowSize, you will have a bigger memory consumption. For a lower windowSize, you will have lower performance and bigger change of seeing blank areas.
权衡:对于更大的windowSize,您将有更大的内存消耗。对于较低的windowSize,您将具有较低的性能和更大的看到空白区域的变化。
legacyImplementation
遗留实现
This prop, when true, make your FlatListrely on the older ListView, instead of VirtualizedList.
这个道具,当为真时,让你FlatList依赖更老的ListView,而不是VirtualizedList。
Win:This will make your list definitely perform better, as it removes virtualization and render all your items at once.
胜利:这肯定会让你的列表表现更好,因为它消除了虚拟化并一次渲染你的所有项目。
Trade offs:Your memory consumption goes to the roof and chances are good that a big list (100+) with complex items will crash your app. It also fires a warning that the above tweaks will not work, because you're now on a ListView.
权衡:您的内存消耗达到顶峰,并且包含复杂项目的大列表(100 多个)很可能会导致您的应用程序崩溃。它还会发出警告,指出上述调整不起作用,因为您现在在 ListView 上。
disableVirtualization
禁用虚拟化
You will see people advocation the use of this prop on some issues. But this is deprecated now. This used to do something similar to legacyImplementation.
你会看到人们在一些问题上提倡使用这个道具。但现在已弃用。这曾经做过类似的事情legacyImplementation。
List items
列出项目
There are also some win-win strategies that involves your list item components. They are being managed by VirtualizedList a lot, so they need to be fast.
还有一些涉及您的列表项组件的双赢策略。它们由 VirtualizedList 管理很多,所以它们需要快速。
Use simple components
使用简单的组件
The more complex your components are, the slower they will render. Try to avoid a lot of logic and nesting in your list items. If you are reusing this list item component a lot in your app, create a duplicate just for your big lists and make them with less logic as possible and less nested as possible.
您的组件越复杂,它们的渲染速度就越慢。尽量避免在列表项中出现大量逻辑和嵌套。如果您在应用程序中大量重复使用此列表项组件,请为您的大列表创建一个副本,并尽可能减少逻辑和嵌套。
Use light components
使用轻量级组件
The heavier your components are, the slower they render. Avoid heavy images (use a cropped version for list items, as small as possible). Talk to your design team, use as little effects and interactions and information as possible in your list. Save them to your item's detail.
您的组件越重,渲染速度就越慢。避免使用过大的图像(对列表项使用裁剪版本,尽可能小)。与您的设计团队交谈,在您的列表中使用尽可能少的效果、交互和信息。将它们保存到您的项目的详细信息中。
Use shouldComponentUpdate
使用 shouldComponentUpdate
Implement update verification to your components. React's PureComponent is mostly for when you don't have time to think. If you're reading this, you do have time, so, create the strictest rules for your list item components. If your list is simple enough, you could even use
对您的组件实施更新验证。React 的 PureComponent 主要用于你没有时间思考的时候。如果您正在阅读本文,那么您确实有时间,因此,为您的列表项组件创建最严格的规则。如果您的列表足够简单,您甚至可以使用
shouldComponentUpdate() {
return false
}
回答by soutot
Here are some improvements you can do to optimize your flatlist:
您可以通过以下改进来优化平面列表:
- Pagination
- You can paginate your data in your backend and refetch it when your scroll gets closer to the end.
onEndReachedandonEndReachedThresholdcan help you.
- You can paginate your data in your backend and refetch it when your scroll gets closer to the end.
- Update your React Native version to 49 or latest
- Fiber 16 has amazing performance improvement which makes everything runs faster and smoother
- Use
PureComponentfor render itemPureComponentimproves the rendering and memory usage of your component, creating render items as pure gives you a better performance experience
- Define
getItemLayoutprop- It improves item rendering since React will previously know its layout definition
- 分页
- 您可以在后端对数据进行分页,并在滚动接近末尾时重新获取它。
onEndReached并且onEndReachedThreshold可以帮助你。
- 您可以在后端对数据进行分页,并在滚动接近末尾时重新获取它。
- 将您的 React Native 版本更新到 49 或最新版本
- Fiber 16 拥有惊人的性能提升,让一切运行得更快更流畅
- 使用
PureComponent的渲染项目PureComponent改进组件的渲染和内存使用,创建纯渲染项可为您提供更好的性能体验
- 定义
getItemLayout道具- 它改进了项目渲染,因为 React 之前会知道它的布局定义
Hope it helps
希望能帮助到你

