🐻优化GIF的内存加载

一、内存OOM问题

使用 UIImage.animatedImage(with:duration:) 方法:UIImage 类提供了一个便利的方法来加载并处理 GIF 图像,该方法可以将 GIF 图像转换为 UIImage 的动画表示。这种方法可以有效地管理内存,并且不需要手动处理每一帧的图像。但会存在内存问题,UIImage(contentsOfFile:) 虽然不会立即放入内存中,但显示时还是会加载到内存中。

ini 复制代码
if let gifURL = Bundle.main.url(forResource: "example", withExtension: "gif") {
    let gifData = try? Data(contentsOf: gifURL)
    let gifImage = UIImage.animatedImage(with: gifData)
    imageView.image = gifImage
}

大量的GIF会导致OOM问题,一旦使用超过系统的阈值,就会崩溃。

二、使用FLAnimatedImageView可以有效的解决GIF内存暴涨的问题

  • FLAnimatedImageView 使用渐进式解码:FLAnimatedImageView 使用渐进式解码来加载 GIF 图片。渐进式解码允许在图片尚未完全加载时就开始显示并逐步增加清晰度。这意味着 FLAnimatedImageView 可以在加载 GIF 图片的同时,逐帧渲染和显示动画,而不需要等待整个 GIF 图片加载完成。这对于大型 GIF 图片特别有利,因为可以显著降低首次加载的延迟,并提高用户体验。
  • 内存优化:FLAnimatedImageView 在加载和显示大型 GIF 图片时进行了内存优化。它只会将当前帧所需的数据加载到内存中,并在显示下一帧时释放之前的帧数据,从而避免占用过多的内存。这有助于在加载大型 GIF 图片时降低内存使用,减少内存压力和 OOM 问题。

三、让FLAnimatedImageView支持网络GIF

FLAnimatedImageView 是用于显示 GIF 动画的 FLAnimatedImage 库中的特殊控件,它并不直接用于加载网络图片,但我们可以扩展方法为其增加加载网络图片的功能。

swift 复制代码
import FLAnimatedImage
import Kingfisher

extension FLAnimatedImageView {
    func setGifImage(withURL url: URL) {
        // 使用 Kingfisher 加载网络图片
        self.kf.setImage(with: url, completionHandler: { result in
            switch result {
            case .success(let value):
                // 成功加载图片,value.image 是 UIImage 类型
                // 将加载的图片转换为 FLAnimatedImage 类型
                let animatedImage = FLAnimatedImage(animatedGIFData: value.image.kf.gifRepresentation())
                // 在 FLAnimatedImageView 中显示 GIF 动画
                self.animatedImage = animatedImage
            case .failure(let error):
                // 加载图片失败,处理错误
                print("Error loading image: (error)")
            }
        })
    }
}

上述方法利用Kingfisher不仅添加了缓存,还能后直接显示来自网络的GIF图片。

四、测试效果

总体内存可以降低70%,CPU在迅速滑动时波动较大,大概为原来的1-2倍,但是停止滑动时降低为原来的50%左右。由于目前iPhone手机的CPU普遍较好,而内存较低;所以这种用CPU缓解内存压力的方法是可行的。

相关推荐
阑梦清川2 小时前
在鱼皮的模拟面试里面学习有感
学习·面试·职场和发展
前端青山9 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
鱼跃鹰飞10 小时前
大厂面试真题-简单说说线程池接到新任务之后的操作流程
java·jvm·面试
程序员清风13 小时前
浅析Web实时通信技术!
java·后端·面试
测试199814 小时前
外包干了2年,快要废了。。。
自动化测试·软件测试·python·面试·职场和发展·单元测试·压力测试
青云交14 小时前
大数据新视界 -- 大数据大厂之 Impala 性能优化:应对海量复杂数据的挑战(上)(7/30)
大数据·性能优化·impala·数据分区·查询优化·海量复杂数据·经典案例
mingzhi6115 小时前
渗透测试-快速获取目标中存在的漏洞(小白版)
安全·web安全·面试·职场和发展
嚣张农民15 小时前
一文简单看懂Promise实现原理
前端·javascript·面试
Liknana17 小时前
Android 网易游戏面经
android·面试
chusheng184017 小时前
Python 爬取大量数据如何并发抓取与性能优化
开发语言·python·性能优化