React Native 性能优化指南

Viewed 0

React Native 性能优化指南

2020年谈React Native,在日新月异的前端圈,可能算比较另类了。但技术文章不是赶时髦,本文旨在分享React Native性能优化的实用指南,通用性强,对大部分RN开发者都适用。本文内容结合了官方推荐、源码分析和优秀开源框架,针对不同团队的使用场景,提供可选的优化建议。

一、减少 re-render

减少re-render是React性能优化中收益最高的方向之一。

1. shouldComponentUpdate

通过shouldComponentUpdate生命周期函数,可以手动比较前后状态的state和props,决定组件是否需要重新渲染。使用时要小心,因为它与业务逻辑强相关,必须考虑所有相关的props和state,避免数据与视图不一致。

官方文档和社区实践(如阅文集团的“元气阅读”应用、Twitter的优化分享)提供了详细参考。

2. React.memo

React.memo是React v16.6引入的高阶组件,专门用于函数组件。默认进行浅比较,也支持传入自定义比较函数。注意,自定义比较函数areEqual的返回值与shouldComponentUpdate相反:props相等时返回true

3. React.PureComponent

React.PureComponent在更新前对props和state进行浅比较。对于复杂嵌套数据,可能不如手动使用shouldComponentUpdate直观。社区解决方案包括细化组件、使用immutable对象等,具体取决于团队选型。

二、减轻渲染压力

React Native的布局依赖Yoga库,将虚拟DOM映射到原生节点。了解映射机制有助于优化布局。

1. 使用 React.Fragment 避免多层嵌套

React.Fragment(或短语法<>)允许组件返回多个节点,减少不必要的View嵌套,适用于自定义组件和官方组件(如ScrollView)。

2. 减少 GPU 过度绘制

过度绘制会影响性能,尤其在Android上。优化建议:

  • 减少背景色的重复设置。
  • 避免设置半透明颜色、圆角和阴影,这些都会引起过度绘制。
    优化应优先考虑Android,但注意iOS和Android的GPU渲染机制不同。

三、图片优化那些事

图片优化涉及缓存、内存管理和加载策略。

1. Image 组件的优化项

Image组件基础功能完善,但作为图片管理库时存在不足:

  • 图片类型:支持png、jpg、base64、gif;Android加载gif需额外配置;iOS不支持webp,需第三方插件。
  • 下载管理:缺乏多图片优先级控制。
  • 缓存管理:可通过HTTP头控制缓存;iOS支持cache属性,Android无直接属性。
  • 多图加载:注意图片文件大小与内存占用的区别。Android可使用resizeMethod属性(resizescaleauto)调整图片尺寸,减少内存占用;通过fadeDuration={0}关闭加载动画。

2. 优先使用 32 位色彩深度的图片

推荐使用32位图片(如带透明度的PNG),因为Android的ARGB_8888格式显示更好,iOS GPU只支持32位图片。但图片来源(设计师或网络)往往不可控,优化收益有限。

3. Image 和 ImageView 长宽保持一致

尺寸不一致会导致模糊、内存浪费和抗锯齿计算。使用PixelRatio.getPixelSizeForLayoutSize根据分辨率加载合适尺寸的图片。

4. 使用 react-native-fast-image

react-native-fast-image底层基于SDWebImage(iOS)和Glide(Android),提供更好的缓存管理、加载优先级和内存优化。但会增加包体积,需权衡。

5. 图片服务器辅助

借助服务端优化:

  • 使用WebP格式减小体积,缩短传输时间。
  • 利用图床定制功能(如七牛云),通过URL参数控制图片宽高和质量,将计算转移至服务端。

四、对象创建调用分离

优化编码习惯,减少不必要的对象创建。

1. public class fields 语法绑定回调函数

使用public class fields语法绑定事件处理函数,避免每次re-render时创建新函数。例如:

handleClick = () => {
    console.log('this is:', this);
}

虽然性能影响小,但有助于保持代码清晰。

2. public class fields 语法绑定渲染函数

类似地,在FlatList等组件中,预先定义渲染函数,避免匿名函数重复创建。

3. StyleSheet.create 替代 StyleSheet.flatten

StyleSheet.create将样式对象优化为StyleID,提升内存和通信效率。StyleSheet.flatten会生成新对象,破坏优化。根据场景权衡通用性与性能。

4. 避免在 render 函数里创建新数组/对象

使用常量(如EMPTY_ARRAY)替代每次渲染时创建的空数组/对象,减少垃圾回收压力。

五、动画性能优化

保证60fps帧率,减少JS线程负担。

1. 开启 useNativeDrive: true

对于可预测的动画,启用原生驱动,将动画配置提前发送到原生端,在UI线程执行,脱离JS线程。仅支持transformopacity等非布局属性。

2. 使用 setNativeProps

直接操作原生节点,避免React重绘。适用于频繁更新的动画,如滚动时数字变化。

3. 使用 InteractionManager

通过InteractionManager.runAfterInteractions()将繁重任务延迟到交互和动画完成后执行,平衡任务与交互。

4. 使用 react-native-reanimated 和 react-native-gesture-handler

这两个库将手势动画移至UI线程运行,避免JS线程计算和异步通信,显著提升复杂手势动画的流畅度。

5. 使用 BindingX

BindingX通过表达式描述交互行为并预置到Native,减少JS与Native通信。适用于富交互场景,但需学习成本。

六、长列表性能优化

虚拟列表核心是只渲染可见区域及附近的View。

1. 列表配置项

VirtualizedList(FlatList底层)的关键配置:

  • initialNumToRender:首批渲染数量,覆盖首屏即可。
  • windowSize:渲染区域高度,一般为视口倍数,控制内存占用与空白View出现几率。
  • removeClippedSubviews:Android默认开启,裁剪子视图提升渲染速度。
  • maxToRenderPerBatchupdateCellsBatchingPeriod:控制增量渲染的数量和时间间隔,平衡渲染与响应速度。

2. ListItems 优化

  • 使用getItemLayout:对于高度固定的Item,直接提供高度和偏移量,避免动态计算。
  • 使用简单组件和轻量组件,减少嵌套和逻辑。
  • 使用shouldComponentUpdate避免不必要的re-render。
  • 使用缓存优化的图片。
  • 使用keyExtractorkey稳定标识。
  • 避免在renderItem中使用匿名函数。

七、React Native 性能优化用到的工具

调试和分析性能时,需结合多端工具:

  • React Native官方调试工具。
  • react-devtools查看React组件树。
  • XCode的instruments和Profiler(iOS)。
  • Android Studio的Android Profiler(Android)。
  • iOS Simulator的Debug选项。
  • Android真机的开发者选项(如GPU渲染分析)。

这些工具帮助定位性能瓶颈,指导优化实践。

0 Answers