【发布时间】:2017-11-07 03:52:30
【问题描述】:
我有一个列表只是简单的文本,它会在 react native 上呈现为平面列表,但我遇到的性能非常非常慢,这使得应用程序无法使用。
我该如何解决这个问题?我的代码是:
<FlatList
data={[{key: 'a'}, {key: 'b'} ... +400]}
renderItem={({item}) => <Text>{item.key}</Text>}
/>
【问题讨论】:
我有一个列表只是简单的文本,它会在 react native 上呈现为平面列表,但我遇到的性能非常非常慢,这使得应用程序无法使用。
我该如何解决这个问题?我的代码是:
<FlatList
data={[{key: 'a'}, {key: 'b'} ... +400]}
renderItem={({item}) => <Text>{item.key}</Text>}
/>
【问题讨论】:
优化平面列表的一种简单方法是使用 React.memo。用技术术语来说,它基本上是对您的数据进行浅层比较,并检查它们是否需要重新渲染。
创建一个文件,例如 ListComponent.js 并将 renderItem JSX 添加到其中,并将其添加到 renderItem。
// ListComponent.js
import React, { memo } from "react";
import { StyleSheet, Text, View } from "react-native";
const ListComponent = ({ item }) => {
return <View ></View>
};
export default memo(ListComponent);
这是您的 FlatList
<FlatList
data={data}
removeClippedSubviews={true}
maxToRenderPerBatch={8}
windowSize={11}
initialNumToRender={8}
keyExtractor={keyExtractor}
renderItem={({ item }) => (
<ListComponent item={item} />
)}
/>
【讨论】:
我使用了“react-native-optimized-flatlist” 我的问题解决了,唯一需要注意的是,当你使用这个包时,它会删除 keyExtractor 和 extraData
【讨论】:
这是我的建议:
A.避免 renderItem 道具上的匿名箭头功能。
将renderItem函数移到render函数之外,这样每次调用render函数时它都不会重新创建自己。
B.尝试在您的 FlatList 上添加 initialNumToRender 属性
它将定义第一次渲染多少个项目,它可以节省一些资源和大量数据。
C.在您的项目组件上定义 key 属性
它会避免在每个项目上定义key 的动态添加/删除项目上重新渲染。确保它是唯一的,不要使用index 作为密钥!您也可以使用keyExtractor 作为替代方案。
D.可选优化
尝试使用getItemLayout 跳过动态内容的测量。还有一些名为maxToRenderPerBatch、windowSize 的道具,您可以使用它们来限制要渲染的项目数量。参考官方文档VirtualizedList或FlatList。
E. Talk is Cheap,给我看代码!
// render item function, outside from class's `render()`
const renderItem = ({ item }) => (<Text key={item.key}>{item.key}</Text>);
// we set the height of item is fixed
const getItemLayout = (data, index) => (
{length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
);
const items = [{ key: 'a' }, { key: 'b'}, ...+400];
function render () => (
<FlatList
data={items}
renderItem={renderItem}
getItemLayout={getItemLayout}
initialNumToRender={5}
maxToRenderPerBatch={10}
windowSize={10}
/>
);
【讨论】:
windowSize={10} 对我来说非常慢且性能降低
getItemLayout + windowSize 非常适合我
查看此链接
https://github.com/filipemerker/flatlist-performance-tips
例子
FlatList
containerContentStyle={styles.container}
data={countries}
renderItem={({ item }) => (
<View style={styles.results}>
<Results
{...this.props}
country={item}
handleUpdate={this.handleUpdate}
pendingCountry={pendingCountry}
/>
</View>
)}
keyExtractor={item => item.alpha2code}
ListHeaderComponent={() => this.renderHeader()}
// Performance settings
removeClippedSubviews={true} // Unmount components when outside of window
initialNumToRender={2} // Reduce initial render amount
maxToRenderPerBatch={1} // Reduce number in each render batch
updateCellsBatchingPeriod={100} // Increase time between renders
windowSize={7} // Reduce the window size
/>
【讨论】:
maxToRenderPerBatch 应该是updateCellsBatchingPeriod
您可以使用 react-native-optimized-flatlist。它是 Flatlist 的优化版本。
1) 通过以下方式添加此包:
npm i -S react-native-optimized-flatlist
或
yarn add react-native-optimized-flatlist
2) 将<FlatList/> 替换为<OptimizedFlatlist/>
【讨论】:
另一个优化是使用keyExtractor 属性提供key。这很重要。
【讨论】:
试试这个列表视图https://github.com/Flipkart/ReactEssentials,它呈现的项目比 FlatList 少得多,然后回收它们。应该快得多。
npm install --save recyclerlistview
【讨论】: