构建高性能 React Native 跨端应用—图片与内存

简介: 介绍 React Native 跨端应用图片和内存的优化

一 前言

在构建高性能 React Native 跨端应用—引擎与渲染章节中,我们从引擎渲染角度介绍了 React Native 的优化手段,本文我们继续从图片内存角度继续讨论一下如何构建高性能的 React Native 应用。

二 图像层面

在浏览器构建的 web 中开发者可能不用花费太多精力关注图像上,但是在移动应用中,对于图像的关注显得非常重要。因为在 RN 应用中,无论是图片还是动图,或者是视频都是非常耗内存的,内存的暴涨就很容易造成应用的崩溃。

图片合理应用

图片的处理,占 RN 性能优化的大头,在现在的移动端应用中,有很多应用大量图片的场景,加载图片的过程实际是很复杂的,并且图片本身的大小,也不是最后加载到内存中的大小,也就是说最后落实在内存里面的大小,会大于图片本身的大小。

图片的处理在不同平台上表现也不一致,在 iOS 平台上对于图像的加载,加密,到最后的展现,表现还算比较好。但是在安卓平台,就时常会出现幺蛾子。

笔者在开发 RN 应用中,就遇到了这样的场景:我们 RN 只运行在安卓端,一个 RN 页面会加载大量的图片,刚开始我们没有对图片进行任何处理,只是图片的宽度和高度是写死的,那么造成的现象是,所有的图片都展现不出来,并且图片是黑的,接下来就是安卓程序直接崩溃。

后来经过排查我们发现,原来我们给图片的容器特别小,但是图片资源却非常大,由于为了在小容器中呈现大的图片,就比如说一个 100 100 图片容器,加载一个 1000 1000 图片,安卓底层需要对图片源数据进行算法压缩,此时就会让内存暴涨,帧率直接降为个位数,导致黑屏,闪退的情况。笔者还把这种小容器加载大图片的情况,叫做小马拉大车。

那么如何解决这个问题呢? RN 中的 Image 组件有个 resizeMethod 属性,就是解决 Android 图片内存暴涨的问题。当图片实际尺寸和容器样式尺寸不一致时,决定以怎样的策略来调整图片的尺寸。

<Image resizeMethod="resize" source={
   
   {
   
    uri: imageUrl  }} />

resizeMethod 属性有三个可选的值,默认为 auto .

resize:小容器加载大图的场景就应该用这个属性。原理是在图片解码之前,会用算法对其在内存中的数据进行修改,一般图片大小大概会缩减为原图的 1/8。
scale:不改变图片字节大小,通过缩放来修改图片宽高。因为有硬件加速,所以加载速度会更快一些。

auto:使用启发式算法来在resize和scale中自动决定,,如果是本地图片,就会用 resize,其他的一般都是 scale 属性,由于项目运用的是网络图片,所以就按照 scale 处理逻辑。

实际最佳的方案就是,适当的大小的图片容器,加载适当的图片。但是对于一些图片资源的大小是未知的,我们不能直接通过设置宽和高的方式草率的设置图片容器大小,解决方案就是可以通过 api 的方式获取远程图片的大小。如下:

import {
   
    Image } from 'react-native'

/* 使用 */
Image.getSize(imageUrl,(width,height)=>{
   
    
    console.log('宽度:',width,'高度:',height)
})

当然客户端也可以把图片压缩的操作交给服务端去做,目前很多大公司都有自己的内建图床和 CDN 服务,会提供一些自定制图片的功能,在请求图片资源的时候,就把图片的宽和高拼接到 url 中,这样服务器接受到图片请求,会根据路径获取 width 和 height,然后自行的对图片进行压缩。返回给客户端的就已经是处理好的能够适配图片容器大小的图片了。

图片管理优化

上面介绍了图片的合理使用,接下来我们看一下图片的管理优化,在 RN 中有多种多样的类型的图片,比如 png/jpg/base64/gif ,对于 gif 在安卓 build.gradle 中需要添加相关依赖。对于一些动图的处理,比如 svg 和 svga ,RN 也提供了相关的生态去处理这些图像。

对图片的管理可以通过不同的场景,运用更为合理的方案。比如对于一些大量 gif 图片的场景,内存就是一个棘手问题,图片的管理工具就需要均衡好内存缓存和磁盘缓存的策略,一般都会采用三级缓存策略。

对于一些网络加载的图片,在一些网络差或者特殊网络的情况下,可以出现加载慢,丢包的现象,这样就会导致图片一致加载失败。庆幸的是,还有专门的图片管理库来来解决这个问题。那就是 react-native-fast-image。

react-native-fast-image 这个库比较受欢迎的,它对图片的加载和内存优化上都有着不错的表现。这个库在 iOS 和安卓平台上,底层用原理也各不相同。

三 内存层面

清除资源

对于清楚资源,谈不上具体的主流优化手段,确切的说,应该是一个值得关注的细节。

比如当 A 页面中有视频播放的模块,而 B 页面是 A 的二级页面,在融合模式下,进入 A 页面之后会开始播放视频流,但是当从 A 页面进入到 B 页面之后,本质上 A 页面并没有被回收,但是这个时候,还在加载着视频资源。那么这样下去,会让内存越来越大。

那么如何解决这个问题呢? 当 A 跳转到 B 页面之后,应该停止 A 页面加载资源,或者清空视频资源,让内存维护一个健康的水平。

对于一些超多 gif 图片的页面,并还有列表加载功能,这样在向下加载数据的过程中,会渲染更多的 gif 组件,这样就会让内存越来越大,并且不容易下来,或者一些低端的机型,根本无法渲染太多的 gif 图片,那么此时应该如何解决呢?

这个时候可以做一个优化,就是只有在视图范围内的元素才渲染真正的 gif 图片,而其他看不见的直接渲染图片或者是占位图。如下所示:

WechatIMG2339.png

清除状态

对于一些全局的状态,比如存在 Redux 中的数据源,或者是全局绑定的监听事件,setTimeout 延时器

四 总结

本文从图像与内存两个方面介绍了 RN 优化手段,希望这篇文章的能给 React Native 开发同学一个性能优化上启发。

参考

相关文章
|
11天前
|
编译器 C语言 C++
C语言学习记录——位段(内存分配、位段的跨平台、位段的应用)
C语言学习记录——位段(内存分配、位段的跨平台、位段的应用)
15 0
|
4天前
|
前端开发 自动驾驶 程序员
鸿蒙? 车载?Flutter? React Native? 为什么我劝你三思,说点不一样的
本文探讨了在信息技术快速发展的背景下,开发者如何选择学习路径。作者提倡使用终局思维来规划职业发展,考虑技术的长远影响。终局思维注重长远目标、系统分析、反向规划和动态调整。以车载开发为例,预测未来智能汽车可能由语音助手主导,而非依赖平板界面。此外,作者建议不要过分投入打工状态,应思考创建自己的产品,如App,以实现技能补充和额外收入。选择对未来发展和自主性有益的技术,如Kotlin,比盲目追求热点更为重要。做减法和有标准的选择,能帮助减轻焦虑,实现更高效的成长。关注公众号“AntDream”获取更多相关内容。
11 1
|
6天前
|
运维 Serverless Nacos
Serverless 应用引擎产品使用合集之在访问量过大的情况下,函数配置的cpu和内存会自动扩容吗
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
6天前
|
开发框架 前端开发 JavaScript
移动应用开发中的跨平台策略:Flutter与React Native的比较
在移动应用领域,跨平台解决方案已成为开发者追求高效、成本效益和广泛覆盖的关键。本文深入探讨了两种领先的跨平台框架——Flutter和React Native,从技术架构、性能、社区生态及实际应用案例四个维度进行全面对比分析。通过这一比较,旨在为移动应用开发者提供选择合适框架的参考依据,帮助他们根据项目需求做出明智的决策。
|
11天前
|
编解码 缓存 Android开发
构建高效的Android应用:从内存优化到响应式设计
【5月更文挑战第37天】 在竞争激烈的移动应用市场中,一个高效、流畅的Android应用是吸引和保留用户的关键。本文将深入探讨构建高效Android应用的多个关键方面,包括内存优化策略、布局性能和响应式设计原则。我们将通过具体的技术实践和案例分析,揭示如何提升应用性能,减少资源消耗,并确保在不同设备上的兼容性和用户体验一致性。
|
13天前
|
前端开发
react怎么做图片报错处理
react怎么做图片报错处理
8 1
|
13天前
|
前端开发 JavaScript Linux
分离前后端react和django3构建的应用
【6月更文挑战第4天】在本文中,我们介绍了如何设置React前端并连接到Django后端。并讨论了前后端分离的好处,并计划扩展API以支持更多HTTP操作和用户身份验证功能。
50 5
分离前后端react和django3构建的应用
|
14天前
|
Python API 前端开发
使用react和django3构建应用
【6月更文挑战第3天】首先,创建Django项目和todos应用,安装必要依赖,配置settings.py并建立数据库模型。通过makemigrations和migrate更新数据库。接着,设置REST_FRAMEWORK的权限为AllowAny,构建API的urls, views, serializers。在todos应用中定义ListTodo和DetailTodo视图,以及TodoSerializer。对于跨域资源共享(CORS),通过django-cors-headers中间件配置白名单。
24 0
|
15天前
|
前端开发 iOS开发 Android开发
React Native跨平台开发实战:从零到一
学习React Native跨平台开发,首先安装Node.js和React Native CLI,设置Android/iOS环境。使用CLI创建项目,如`npx react-native init MyProject`。运行应用:`npx react-native run-android`或`run-ios`。编写组件,如在App.js中创建Hello World。添加样式,安装第三方库如react-native-vector-icons,使用react-navigation进行路由和导航。
20 2
|
15天前
|
C++ 存储 Java
C++ 引用和指针:内存地址、创建方法及应用解析
'markdown'C++ 中的引用是现有变量的别名,用 `&` 创建。例如:`string &meal = food;`。指针通过 `&` 获取变量内存地址,用 `*` 创建。指针变量存储地址,如 `string *ptr = &food;`。引用不可为空且不可变,指针可为空且可变,适用于动态内存和复杂数据结构。两者在函数参数传递和效率提升方面各有优势。 ```

热门文章

最新文章