名称: 性能优化器 描述: 优化React Native应用性能,包括桥梁优化、列表渲染、内存管理和性能剖析。适用于应用慢、卡顿或内存消耗过高的情况。触发词包括“性能”、“优化”、“慢”、“卡顿”、“内存”、“FlatList”、“渲染”。
性能优化器
优化React Native应用在渲染、桥梁通信和内存使用方面的性能。
快速开始
常见性能问题及快速修复:
- 慢列表:使用FlatList并设置适当的优化属性
- 桥梁瓶颈:批量操作,使用原生模块
- 内存泄漏:清理监听器、定时器、订阅
- 慢动画:使用原生驱动,Reanimated库
说明
步骤1:剖析和识别瓶颈
启用性能监视器:
// 摇晃设备 → "显示性能监视器"
// 或在代码中(仅开发模式):
if (__DEV__) {
require('react-native').PerformanceLogger.startTimespan('应用启动');
}
使用React DevTools剖析器:
npm install -g react-devtools
react-devtools
使用Flipper:
- 安装Flipper桌面应用
- 启用React DevTools、网络、Hermes调试器插件
- 剖析组件渲染和桥梁调用
常见瓶颈:
- 过多重新渲染
- 桥梁通信开销
- 大型列表渲染
- 内存泄漏
- 未优化图像
步骤2:优化组件渲染
使用React.memo:
import React, { memo } from 'react';
const 昂贵组件 = memo(({ data }) => {
return <View>{/* 昂贵渲染 */}</View>;
});
// 使用自定义比较
const 昂贵组件 = memo(
({ data }) => <View>{data.value}</View>,
(prevProps, nextProps) => prevProps.data.id === nextProps.data.id
);
使用useMemo和useCallback:
import { useMemo, useCallback } from 'react';
function 我的组件({ items, onPress }) {
// 记忆昂贵计算
const 排序项 = useMemo(
() => items.sort((a, b) => a.value - b.value),
[items]
);
// 记忆回调以防止子组件重新渲染
const 处理按下 = useCallback(
(id) => onPress(id),
[onPress]
);
return <List items={排序项} onPress={处理按下} />;
}
避免内联函数和对象:
// 不好 – 每次渲染创建新函数
<Button onPress={() => 处理按下(item.id)} />
// 好 – 使用useCallback
const 处理项按下 = useCallback(() => 处理按下(item.id), [item.id]);
<Button onPress={处理项按下} />
// 不好 – 每次渲染创建新对象
<View style={{ marginTop: 10 }} />
// 好 – 定义外部或使用StyleSheet
const 样式 = StyleSheet.create({
容器: { marginTop: 10 }
});
<View style={样式.容器} />
步骤3:优化列表渲染
使用FlatList并设置优化属性:
import { FlatList } from 'react-native';
<FlatList
data={items}
renderItem={({ item }) => <项 data={item} />}
keyExtractor={(item) => item.id}
// 性能优化
removeClippedSubviews={true}
maxToRenderPerBatch={10}
updateCellsBatchingPeriod={50}
initialNumToRender={10}
windowSize={5}
// 如果项高度固定
getItemLayout={(data, index) => ({
length: 项高度,
offset: 项高度 * index,
index,
})}
/>
使用FlashList以获得更好性能:
npm install @shopify/flash-list
import { FlashList } from '@shopify/flash-list';
<FlashList
data={items}
renderItem={({ item }) => <项 data={item} />}
estimatedItemSize={100}
/>
优化列表项:
// 记忆列表项
const 项 = memo(({ data }) => {
return (
<View>
<Text>{data.title}</Text>
</View>
);
});
// 类组件使用PureComponent
class 项 extends PureComponent {
render() {
return <View>{this.props.data.title}</View>;
}
}
步骤4:优化桥梁通信
批量桥梁调用:
// 不好 – 多次桥梁调用
items.forEach(item => {
NativeModule.处理项(item);
});
// 好 – 单次桥梁调用
NativeModule.处理项组(items);
使用InteractionManager:
import { InteractionManager } from 'react-native';
// 延迟昂贵操作直到动画后
InteractionManager.runAfterInteractions(() => {
// 昂贵操作
处理数据();
});
将繁重操作移至原生:
// 对于CPU密集型任务,创建原生模块
import { NativeModules } from 'react-native';
const { 繁重计算 } = NativeModules;
const 结果 = await 繁重计算.处理(大数据集);
步骤5:优化图像
使用FastImage:
npm install react-native-fast-image
import FastImage from 'react-native-fast-image';
<FastImage
source={{
uri: 图像URL,
priority: FastImage.priority.normal,
cache: FastImage.cacheControl.immutable,
}}
resizeMode={FastImage.resizeMode.cover}
style={{ width: 200, height: 200 }}
/>
优化图像大小:
// 使用适当图像大小
<Image
source={{ uri: 图像URL }}
style={{ width: 100, height: 100 }}
resizeMode="cover"
/>
// 预加载图像
FastImage.preload([
{ uri: 图像1URL },
{ uri: 图像2URL },
]);
使用WebP格式:
- 文件大小比PNG/JPEG小
- 支持iOS和Android
- 转换图像:
cwebp 输入.png -o 输出.webp
步骤6:优化动画
使用原生驱动:
import { Animated } from 'react-native';
const 淡入淡出动画 = new Animated.Value(0);
Animated.timing(淡入淡出动画, {
toValue: 1,
duration: 1000,
useNativeDriver: true, // 启用原生驱动
}).start();
使用Reanimated进行复杂动画:
npm install react-native-reanimated
import Animated, {
useAnimatedStyle,
withTiming,
useSharedValue,
} from 'react-native-reanimated';
function 动画组件() {
const 偏移量 = useSharedValue(0);
const 动画样式 = useAnimatedStyle(() => ({
transform: [{ translateX: withTiming(偏移量.value) }],
}));
return <Animated.View style={动画样式} />;
}
步骤7:修复内存泄漏
清理监听器:
useEffect(() => {
const 订阅 = 事件发射器.addListener('事件', 处理器);
return () => {
订阅.remove(); // 清理
};
}, []);
清理定时器:
useEffect(() => {
const 定时器 = setTimeout(() => {
// 做某事
}, 1000);
return () => {
clearTimeout(定时器); // 清理
};
}, []);
清理异步操作:
useEffect(() => {
let 已取消 = false;
async function 获取数据() {
const 结果 = await api.获取();
if (!已取消) {
setData(结果);
}
}
获取数据();
return () => {
已取消 = true; // 防止卸载后状态更新
};
}, []);
常见模式
虚拟化列表
import { VirtualizedList } from 'react-native';
<VirtualizedList
data={items}
renderItem={({ item }) => <项 data={item} />}
keyExtractor={(item) => item.id}
getItemCount={(data) => data.length}
getItem={(data, index) => data[index]}
/>
懒加载
import React, { lazy, Suspense } from 'react';
const 繁重组件 = lazy(() => import('./繁重组件'));
function 应用() {
return (
<Suspense fallback={<加载中 />}>
<繁重组件 />
</Suspense>
);
}
防抖和节流
import { useCallback } from 'react';
import debounce from 'lodash/debounce';
function 搜索组件() {
const 防抖搜索 = useCallback(
debounce((查询) => {
执行搜索(查询);
}, 300),
[]
);
return (
<TextInput
onChangeText={防抖搜索}
placeholder="搜索..."
/>
);
}
分页
function 无限列表() {
const [页, set页] = useState(1);
const [项, set项] = useState([]);
const [加载中, set加载中] = useState(false);
const 加载更多 = async () => {
if (加载中) return;
set加载中(true);
const 新项 = await 获取项(页);
set项([...项, ...新项]);
set页(页 + 1);
set加载中(false);
};
return (
<FlatList
data={项}
renderItem={({ item }) => <项 data={item} />}
onEndReached={加载更多}
onEndReachedThreshold={0.5}
ListFooterComponent={加载中 ? <加载中 /> : null}
/>
);
}
剖析工具
React DevTools剖析器
// 包裹组件以剖析
import { Profiler } from 'react';
function onRender回调(
id,
阶段,
实际持续时间,
基础持续时间,
开始时间,
提交时间
) {
console.log(`${id} 渲染花费 ${实际持续时间}ms`);
}
<Profiler id="我的组件" onRender={onRender回调}>
<我的组件 />
</Profiler>
性能监视
import { PerformanceObserver, performance } from 'react-native-performance';
const 观察者 = new PerformanceObserver((列表) => {
列表.getEntries().forEach((条目) => {
console.log(`${条目.name}: ${条目.duration}ms`);
});
});
观察者.observe({ entryTypes: ['measure'] });
performance.mark('开始');
// ... 操作
performance.mark('结束');
performance.measure('操作', '开始', '结束');
故障排除
应用感觉迟缓:
- 使用React DevTools剖析
- 检查过多重新渲染
- 优化列表渲染
- 动画使用原生驱动
高内存使用:
- 检查内存泄漏(监听器、定时器)
- 优化图像大小
- 为大型列表实现分页
- 使用Xcode Instruments(iOS)或Android Profiler剖析
慢启动:
- 减少初始包大小
- 懒加载组件
- 优化原生模块初始化
- 使用Hermes引擎
卡顿动画:
- 使用原生驱动
- 避免动画期间的桥梁调用
- 复杂动画使用Reanimated
- 减少布局复杂性
最佳实践
- 先剖析:在优化前识别实际瓶颈
- 适当记忆:不过度优化,通过剖析确认
- 优化列表:使用FlatList/FlashList并设置适当属性
- 原生驱动:动画尽可能使用
- 清理:移除监听器、定时器、订阅
- 批量操作:最小化桥梁调用
- 懒加载:按需加载组件和数据
- 监视:在生产中跟踪性能指标