logo

优化React Native中的用户体验,以及解决性能问题

1706
2024年02月13日
你如何让你的应用运行得更快并提高其整体质量?考虑问题和实际解决方案以提高React Native应用的效率。

一天,我所在的公司决定需要一个移动应用。我们的前端团队自愿帮助这个有趣的项目。众所周知,如果你是前端开发人员,尤其是使用React库进行开发,React Native是开发移动应用的最佳方式。这就是我们开始着手开发我们的WMS应用的方式。

随着应用的不断发展,我们开始考虑其性能检查和优化方式。

我们的计划是:

  1. 确定问题所在
  2. 测量可测量的内容(不要凭直觉)
  3. 分析
  4. 如有必要,进行改进
  5. 保持控制

那时,我们的应用包含两个主要部分——导航和可滚动列表。我们使用不同的工具来检查每个部分的性能。

基本上,在大多数性能检查工具中,绿色表示实际上很好,黄色表示有改进的空间,但应用仍然可以正常工作,红色表示你的应用和客户都需要帮助。

我们确定了一些问题,第一个问题主要与负责导航的抽屉组件的渲染时间有关:

React DevTools的应用分析器

React DevTools的应用分析器

我们还检查了我们应用的性能:

Flipper + RN性能监视器的应用性能

Flipper + RN性能监视器的应用性能

我们发现导航的性能几乎降至0。这个问题已经存在很长时间,并且在文档中有描述。简而言之,当推送一个新屏幕时,React Navigation首先在屏幕外渲染它,然后再将其动画显示到位。因此,如果有一个屏幕上有很多组件,很容易需要几百毫秒来渲染。

我们的应用内有很多嵌套的导航器,所以我们面临了这个问题。在React Navigation库发布修复之前,有一种避免这个问题的方法——不要使用太多的导航器,尽量减少嵌套。另外,你可以尝试使用InteractionManager来推迟繁重的计算。

第二个问题与我们的可滚动列表有关:

React DevTools的可滚动列表分析器

React DevTools的可滚动列表分析器

可滚动列表

可滚动列表

在滚动过程中,我们测量了性能,结果显示如下:

Flipper + RN性能监视器的可滚动列表性能

Flipper + RN性能监视器的可滚动列表性能

虽然不算太糟糕,但肯定有一些地方需要优化。我们从代码和组件入手。基本上,我们有一个带有渲染数据的FlatList组件。首先要检查的是我们如何在那里使用记忆化。例如,我们需要扫描条形码并获取特定数据,然后根据这些数据显示相关列表。如果我们扫描相同的条形码,整个屏幕会重新渲染,因为它认为有新数据进来了。为了避免这种情况,我们需要分析哪些组件经常重新渲染,并尝试使用useCallbackuseMemoReact.memo等方法来记忆化函数、变量和属性。但要记住,只在实际需要的地方使用,因为过度记忆化可能会进一步降低应用的性能。因此,只在需要进行昂贵计算时使用useMemo,只在组件经常以相同的props重新渲染且组件相对较大时使用React.memo,只在组件接受依赖于引用相等性的函数时使用useCallback。当然,这并不是所有的使用情况,但是常见的情况。

接下来要检查的是我们可滚动列表的主要组件的实现:

    <FlatList
      data={skuInfo}
      renderItem={({ item: sku }) => <SkuCard {...sku} />}
      keyExtractor={sku => sku.id}
    />

我们回到文档,复习了一下。文档建议不要在renderItem属性中使用箭头函数。此外,renderItem组件应该是一个记忆化的组件,以避免不必要的重新渲染。

  // SkuCard组件的修复
  export default memo(SkuCard);

  // FlatList的renderItem属性的修复
  const renderItem = useCallback(
    ({ item: sku }: { item: SKUInfo }) => <SkuCard {...sku} />,
    [],
  );

  // 修复后的FlatList的样子
  <FlatList
    data={skuInfo}
    renderItem={renderItem}
    keyExtractor={sku => sku.id}
  />

我们在这些改变后检查了可滚动列表的分析器:

React DevTools的可滚动列表分析器

React DevTools的可滚动列表分析器

这有助于大大优化渲染部分。此外,我们还查看了性能:

Flipper + RN性能监视器的可滚动列表性能

Flipper + RN性能监视器的可滚动列表性能

好多了。那时,我们的应用规模还很小,随着它的发展,我们将需要更多地监控性能。

另外,记住你可以使用Shopify提供的一些不错的工具,比如FlashList,你可以尝试在你的应用中实现。

结论

  1. 避免使用大量的导航器,尽量减少嵌套。
  2. 推迟计算和繁重渲染,使用InteractionManager来避免它们影响UI的性能。
  3. 尝试在首次渲染时为屏幕的繁重部分渲染占位符,然后在动画完成后用实际内容替换它们。
  4. 分析应用的不同部分,看看是React Navigation占用了大部分时间,还是你的应用组件逻辑可以优化。
  5. 谨慎使用外部库。在应用特定库之前和之后比较性能,决定哪个对你的应用更好。
本文链接:https://www.iokks.com/art/f10f11882180
本博客所有文章除特别声明外,均采用CC BY 4.0 CN协议 许可协议。转载请注明出处!