ReactNative显示优化

场景ReactNactive性能问题
ReactNative性能优化点

减少Bundle包的大小

关于如何减少Bundle包的大小,目前主流的方法是拆分Bundle包,把框架代码和业务代码单独出来,框架代码非常大,因此要分离出来单独前置加载,而业务代码则变成很小的JS代码单独发布,下面提供一些前人的经验链接

那么进入App后的性能点又在哪里呢?还是回到Bridge
首先,在苹果和谷歌两位大佬的光环下,native代码在设备上的运行速度毋容置疑,而JS作为脚本语言,本来就是以快著称,也就是说两边的独立运行都很快,如此看来,性能瓶颈只会出现在两端的通信上,但两边其实不是直接通信的,而是通过Bridge做中间人,查找、调用模块、接口等操作逻辑,会产生到能让UI层明显可感知的卡顿,那么性能控制就变成了如何尽量减少Bridge所需要的逻辑。

  • UI事件响应
    • 这块内容都发生在Native端,以事件形式传递到JS端,只是一个触发器,不会有过度性能问题
  • UI更新
    • JS是决定显示什么界面,如何样式化页面的,一般都是由JS端发起UI更新,同时向native端同步大量的数据和UI结构,这类更新会经常出现性能问题,特别是界面复杂、数据变动量大、动画复杂、变动频率高的情况
  • UI事件响应+UI更新
    • 如果UI更新改动不大,那么问题不大 如果UI事件触发了UI更新,同时逻辑复杂、耗时比较长,JS端和Native端的数据同步可能会出现时间差,由此会引发性能问题

总结起来,核心的RN性能优化点就比较清晰明朗了

  • 首屏渲染优化:处理JS Bundle包大小、文件压缩、缓存
  • 提高组件响应速度:
    • setNativeProps直接在底层更新Native组件属性(其实没有解决JS端与Native端的数据同步问题)
    • 立即执行更新回调(requestAnimationFrame)
  • 动画优化
    • 通过使用Annimated类库,一次性把更新发送到Native端,由Native端自己负责更新
    • 把一些耗时操作放到动画与UI更新之后执行(InteractionManager)

图片加载

1:这种场景往往是小尺寸 Image 容器加载了特别大的图片,比如说 100x100 的容器加载 1000x1000 的图片那么这种问题怎么解决呢?Image 有个 resizeMethod 属性,就是解决 Android 图片内存暴涨的问题。当图片实际尺寸和容器样式尺寸不一致时,决定以怎样的策略来调整图片的尺寸。
顺便提一下,Android 图片加载的时候,还会有一个 easy-in 的 300ms 加载动画效果,看上去会觉得图片加载变慢了,我们可以通过设置 fadeDuration 属性为 0,来关闭这个加载动画。
2:优先使用 32 位色彩深度的图片
为啥推荐使用 32 bit 图片呢?直接原因有 2 个:

  • Android 推荐使用 ARGB_8888 格式的图片,因为这种图片显示效果更好
  • iOS GPU 只支持加载 32 bit 的图片。如果是其他格式的(比如说 24 bit 的 jpg),会先在 CPU 里转为 32 bit,再传给 GPU

3:Image 和 ImageView 长宽保持一致
前面举了一个 100x100 的 ImageView 加载 1000x1000 Image 导致 Android 内存 OOM 的问题,我们提出了设置 resizeMethod={‘resize’} 的方法来缩减图片在内存中的体积。其实这是一种无奈之举,如果可以控制加载图片的大小,我们应该保持 Image 和 ImageView 长宽一致。
首先我们看看长宽不一致会引起的问题:

  • Image 小于 ImageView:图片不清晰,表情包电子包浆质感
  • Image 大于 ImageView:浪费内存,有可能会引起 OOM
  • 尺寸不一致会带来抗锯齿计算,增加了图形处理负担

延时加载模块或文件

import React, { Component } from 'react';
import { Text } from 'react-native';
// You may want to log at the file level to verify when this is happening
console.log('VeryExpensive component loaded');


export default class VeryExpensive extends Component {
  // lots and lots of code
  render() {
    return <Text>Very Expensive Component</Text>;
  }
}
import React, { Component } from 'react';
import { TouchableOpacity, View, Text } from 'react-native';


// 先把这个组件赋值为null
let VeryExpensive = null;


export default class Optimized extends Component {
  state = { needsExpensive: false };


  didPress = () => {
    if (VeryExpensive == null) {
                // 真正需要这个组件的时候才加载
      VeryExpensive = require('./VeryExpensive').default;
    }


    this.setState(() => ({
      needsExpensive: true,
    }));
  };


  render() {
    return (
      <View style={{ marginTop: 20 }}>
        <TouchableOpacity onPress={this.didPress}>
          <Text>Load</Text>
        </TouchableOpacity>
                  // 根据需要判断是否渲染该组件
        {this.state.needsExpensive ? <VeryExpensive /> : null}
      </View>
    );
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值