跳至主内容
版本:0.77

优化 FlatList 配置

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

术语表

  • VirtualizedList: FlatList 的底层组件(React Native 对Virtual List概念的实现)

  • 内存消耗 (Memory consumption): 列表信息在内存中的存储量,过高可能导致应用崩溃

  • 响应性 (Responsiveness): 应用响应交互的能力。例如低响应性表现为触摸组件后出现延迟响应,而非预期的即时反馈

  • 空白区域 (Blank areas):VirtualizedList 渲染速度不足时,列表会出现未渲染组件形成的空白区块

  • 视口 (Viewport): 实际渲染为像素的可见内容区域

  • 窗口 (Window): 组件应被挂载的区域,通常远大于视口范围

属性

以下参数可帮助提升 FlatList 性能:

removeClippedSubviews

TypeDefault
Booleantrue on Android, otherwise false

若为 true,位于视口之外的视图会自动从原生视图层级中分离。

优点: 通过排除视口外视图的原生渲染和绘制遍历,减少主线程耗时,降低掉帧风险

缺点: 该实现可能存在缺陷(尤其在 iOS 平台),例如内容缺失(常见于复杂变换/绝对定位场景)。注意这不会显著节省内存,因为视图仅被分离而非释放

maxToRenderPerBatch

TypeDefault
Number10

可通过 FlatList 传递的 VirtualizedList 参数,控制每次滚动时渲染的批次项目数量

优点: 增大数值可减少滚动时的视觉空白区域(提升填充率)

缺点: 每批次项目增多可能导致 JavaScript 执行时间过长,阻塞点击等事件处理,影响响应性

updateCellsBatchingPeriod

TypeDefault
Number50

maxToRenderPerBatch 控制每批渲染数量,而设置 updateCellsBatchingPeriod 则告诉你的 VirtualizedList 批次渲染间的毫秒级延迟(决定窗口化项目的渲染频率)

优点: 结合此参数与 maxToRenderPerBatch 可实现灵活配置,例如低频次渲染更多项目或高频次渲染较少项目

缺点: 低频批次可能导致空白区域,高频批次可能引发响应性问题

initialNumToRender

TypeDefault
Number10

初始渲染的项目数量

优点: 精确定义覆盖各类设备屏幕所需数量,可大幅提升初始渲染性能

缺点:initialNumToRender 设置过低可能导致空白区域(尤其在初始渲染无法覆盖视口时)

windowSize

TypeDefault
Number21

数值单位 1 等同于视口高度,默认值 21(上方 10 视口 + 下方 10 视口 + 中间 1 视口)

优点: 增大 windowSize 可降低滚动空白风险,减小 windowSize 则减少同时挂载项目以节省内存

缺点: windowSize 越大内存消耗越高,windowSize 越小出现空白区域的概率越大

列表项

以下是一些关于列表项组件的优化技巧。它们是列表的核心,因此需要保持高效。

使用基础组件

组件越复杂,渲染速度越慢。尽量避免在列表项中嵌套过多逻辑和组件层级。如果需要在应用中复用该列表项组件,建议为长列表专门创建极简化的组件,尽可能减少逻辑处理和嵌套层级。

使用轻量组件

组件越重,渲染越慢。避免使用大尺寸图片(列表项中应使用裁剪版或缩略图,尺寸越小越好)。与设计团队沟通,在列表中尽量精简特效、交互动效和信息展示,这些内容可移至详情页呈现。

使用 memo()

React.memo() 创建的记忆化组件仅在传入属性变更时才会重新渲染。我们可以利用该函数优化 FlatList 中的组件性能。

tsx
import React, {memo} from 'react';
import {View, Text} from 'react-native';

const MyListItem = memo(
({title}: {title: string}) => (
<View>
<Text>{title}</Text>
</View>
),
(prevProps, nextProps) => {
return prevProps.title === nextProps.title;
},
);

export default MyListItem;

在下方示例中,我们设定了 MyListItem 组件仅在 title 属性变更时重新渲染。通过向 React.memo() 传入比较函数作为第二个参数,可确保组件仅在指定属性变化时更新。若比较函数返回 true,组件将跳过渲染。

使用缓存的优化图像

您可以使用社区包(例如 Dream11@d11/react-native-fast-image)获取更高性能的图片。列表中的每张图片都是 new Image() 实例,图片加载越快到达 loaded 钩子,JavaScript 线程就能越快恢复空闲。

使用 getItemLayout

当所有列表项具有相同高度(或水平列表的宽度)时,提供 getItemLayout 属性可免除 FlatList 的异步布局计算需求,这是非常推荐的优化手段。

若组件尺寸动态变化又亟需性能提升,可考虑与设计团队沟通是否接受优化导向的重新设计。

使用 keyExtractor 或 key

FlatList 设置 keyExtractor 属性,该属性用于缓存机制并作为 React 的 key 追踪项目重排序。

也可直接在列表项组件中使用 key 属性。

避免在 renderItem 上使用匿名函数

函数式组件中,请将 renderItem 函数移至 JSX 返回结构外部,并用 useCallback 钩子包裹以避免每次渲染时重新创建。

类组件中,将 renderItem 函数移出 render 方法,防止每次调用 render 时重新创建函数。

tsx
const renderItem = useCallback(({item}) => (
<View key={item.key}>
<Text>{item.title}</Text>
</View>
), []);

return (
// ...

<FlatList data={items} renderItem={renderItem} />;
// ...
);