移动App中使用网络图片的情况很常见,如果缓存问题处理不好会很大程度上影响App的性能。本文简单介绍一下图片缓存流程及GitHub上现有解决方案。

一般图片缓存及使用流程

最简单的缓存方式:

1
2
3
4
let imgData = NSData(contentsOfURL: NSURL(string: "http://7narze.com1.z0.glb.clouddn.com/1.jpg")!)
imgData?.writeToFile("cache patch", atomically: true)
let img = UIImage(data: imgData!)
imgView.image = img

很明显,下载图片和缓存图片时有主线程阻塞。那么优化成下面的样子:

1
2
3
4
5
6
7
8
dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)) { () -> Void in
let imgData = NSData(contentsOfURL: NSURL(string: "http://7narze.com1.z0.glb.clouddn.com/1.jpg")!)
imgData?.writeToFile("cache patch", atomically: true)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let img = UIImage(data: imgData!)
imgView.image = img
})
}

这样是在子线程下载并缓存,性能上会好很多,但很明显这样不够用。

一般缓存流程

一般流程

从上图,可以看出还有很多可优化点

1
2
3
4
5
6
7
异步下载
子线程解压缩
使用缓存 (内存/磁盘)
缓存解压缩后的图片
减少内存级别的拷贝
良好的接口
图片预下载

现有解决方案

好,下面我们简单介绍下目前GitHub上比较流行(star数据大于2000)的图片缓存库。

SDWebImage

基础流程
SDWebImage流程

  • 优点
    • 健全的Category
    • SDWebImagePrefetcher预加载
    • 独立的下载模块/缓存模块
    • 自定义age
  • 缺点
    • 因缓存的图片数据已解码,故占用空间变大(这个也算不上缺点)
    • 没有处理减少内存级别的拷贝和字节对齐(FastImageCache对此有处理)
    • 图片属于静态资源,没有判断Cache-ControlLast-ModifiedETag(通用库做到这点有些麻烦)

Kingfisher

SDWebImageSwift

流程基本和SDWebImage一致

  • 优点
    • Swift编写
    • 使用很多最新API
    • 其他同SDWebImage
  • 缺点
    • iOS 8 later
    • 其他同SDWebImage

AFNetworking

基础流程图
AFNetworking流程

  • 优点
    • 健全的Category
    • 缓存机制可定制(实现AFImageCache)
    • 依附AFNetworking
  • 缺点
    • 功能单一
    • 缓存仅在内存中(默认实现)

FastImageCache

无网络缓存功能,但却是图片加载速度极限优化

总结

实际应用中推荐SDWebImage/Kingfisher结合FastImageCache使用。若要考虑HTTP的缓存机制,可以自己继承/实现封装。


评论

2016-03-22
阿P