构建高性能 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 开发同学一个性能优化上启发。

参考

相关文章
|
3天前
|
存储 监控 算法
内存泄漏还是高性能?深度揭秘.NET垃圾回收机制
【8月更文挑战第28天】垃圾回收是.NET框架中自动化内存管理的关键机制,它通过分代收集算法自动清理不再使用的对象,简化了开发者的内存管理工作。本文深入解析了垃圾回收器的工作原理、对象内存分配策略及优化技巧,并介绍了多种监控工具,帮助提升.NET应用性能与稳定性。掌握这些知识将使开发者能够更高效地管理内存,提高应用程序的运行效率。
13 3
|
2天前
|
前端开发 应用服务中间件 nginx
[译] 面向 React 和 Nginx 的 Docker 多阶段构建
[译] 面向 React 和 Nginx 的 Docker 多阶段构建
[译] 面向 React 和 Nginx 的 Docker 多阶段构建
|
2月前
|
存储 前端开发 JavaScript
深入浅出React框架:构建高效组件化网页的实战指南
【7月更文挑战第9天】在当今快速发展的前端技术领域,React凭借其强大的组件化思想、高效的虚拟DOM以及丰富的生态系统,成为了构建动态用户界面的首选框架之一。本文将带你深入浅出地探索React的核心概念,并通过实战示例,展示如何利用React构建高效、可维护的组件化网页。
73 8
|
3月前
|
前端开发 JavaScript Linux
分离前后端react和django3构建的应用
【6月更文挑战第4天】在本文中,我们介绍了如何设置React前端并连接到Django后端。并讨论了前后端分离的好处,并计划扩展API以支持更多HTTP操作和用户身份验证功能。
82 5
分离前后端react和django3构建的应用
|
3月前
|
存储 缓存 NoSQL
Redis是一种高性能的内存数据库,常用于高并发环境下的缓存解决方案
【6月更文挑战第18天】**Redis摘要:** 高性能内存数据库,擅长高并发缓存。数据存内存,访问迅速;支持字符串、列表等多元数据类型;具备持久化防止数据丢失;丰富命令集便于操作;通过节点集群实现数据分片与负载均衡,增强可用性和扩展性。理想的缓存解决方案。
53 1
|
2月前
|
设计模式 存储 缓存
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
38 0
|
4月前
|
前端开发 JavaScript API
使用React和GraphQL构建一个简单的博客应用
使用React和GraphQL构建一个简单的博客应用
36 1
|
3月前
|
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中间件配置白名单。
50 0
|
19天前
|
前端开发 JavaScript UED
React 基础与实践 | 青训营笔记
React 基础与实践 | 青训营笔记
28 0
|
2月前
|
前端开发 JavaScript Java
React 速通笔记
【7月更文挑战第17天】
31 1

热门文章

最新文章

下一篇
云函数