SDWebImage框架的学习
这个库是一个支持缓存的图片异步加载库。为了方便使用,SDWebImage为一些UI控件,如UIView,UIImageView,UIButton,MKAnnotationView添加了分类。
这个框架的几大特征:
- 在UIImageView,UIButton,MKAnnotationView的类目中添加了网络图片和缓存的管理;
- 异步图片加载器;
- 带有自动缓存过期处理的异步内存+磁盘图片缓存机制;
- 后台图片解压;
- 同一个URL不会被多次下载;
- 虚假URL不会被重复尝试下载;
- 主线程不会被阻塞;
- 高性能;
- 使用GCD和ARC;
支持的图片格式:
- 支持JPEG,PNG…等图片格式,包括GIF;
- WebP格式,包括动画WebP;
要求: - iOS7.0及以后的系统;
- tvOS9.0及之后的系统;
- watchOS2.0及之后的系统;
- macOS10.9及之后的系统;
- Xcode7.3及之后的系统;
使用方法:
#import <SDWebImage/UIImageView+WebCache.h>
...
[imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
下来我们根据SDWebImage的结构图和流程图,来梳理SDWebImage加载图片的步骤和原理:
1、首先,为了能看懂下面的结构图,我们先来看一下OMT(Object-Modeling Technique)图示法中的各个标记的含义。
UML图的表示.png
2、下面,来看SDWebImage框架的结构图:
SDWebImageClassDiagram.png
3、流程图:
SDWebImageSequenceDiagram.png
对于结构图和流程图,我们可以先不具体看,而是从我们的1中的包含文件说起。
用使用SDWebImage就需要先包含SDWebImage包下的UIImageView+WebCache头文件。
因此,
(1)我们先在结构图中找到UIImageView+WebCache这个分类文件,这个分类暴露了一个叫做 - (void)sd_setImageWithURL:(nullable NSURL *)url的方法给我们用。
(2)从结构图中,可以看出这个方法依赖于UIImageView的父类UIView的分类 UIView+WebCache中的 sd_internalSetImageWithURL方法。
(3)同样的, UIView+WebCache中的 sd_internalSetImageWithURL方法又依赖于 SDWebImageManager中的 loadImageWithURL方法。
(4)SDWebImageManager中的 loadImageWithURL方法,就是我们获取图片的关键步骤了。
(4.1)在SDWebImageManager中SDImageCache和SDWebImageDownloader是其中的一部分,因此说SDWebImageManager和SDImageCache、SDWebImageDownloader的引用之间构成聚合关系;
(4.2)SDImageCache的引用需要调用 queryCacheOperationForKey方法来在缓存中查询该url对应的图片缓存,并返回。
(4.3)SDWebImageDownloader的引用需要调用 downloadImageWithURL方法去下载URL所对应的图片,并返回。
(4.4)对于下载成功的图片,需要SDImageCache的引用调用 storeImage方法将下载完成的图片储存在缓存中,以便下次调用。
以上,我们就对SDWebImage的框架和工作流程有了一个大致的了解。
下面,我们对SDWebImage的几大特性,来分析一下其源码,是怎么实现的?
缓存图片有三种类型:
//图片不在缓存中,而是从网络下载的
SDImageCacheTypeNone,
//图片是磁盘中获取的
SDImageCacheTypeDisk,
//图片是从内存缓存中获取的
SDImageCacheTypeMemory
图片缓存选项的类型也有三种:
//默认情况下,当图片缓存在内存中时,我们不会查询磁盘数据。这种类型会强制同时查询磁盘数据
SDImageCacheQueryDataWhenInMemory = 1 << 0,
//默认情况下,我们是同步查询内存缓存,异步查询磁盘数据。这种类型会强制同步查询磁盘数据
SDImageCacheQueryDiskSync = 1 << 1,
//默认情况下,图片按照原本尺寸解码。iOS中,这个标志位会把图片缩小到个设备内存兼容的尺寸。
SDImageCacheScaleDownLargeImages = 1 << 2
1、在UIImageView,UIButton,MKAnnotationView的分类中添加了网络图片和缓存的管理;
在SDWebImage的WebCache Categories目录下,是关于UIImageView,UIButton,MKAnnotationView的分类,其中暴露给我们可以通过传入URL加载网络图片的方法;
2、异步图片加载器;
通过传入图片URL开始加载图片的过程主要在SDWebImageManager的loadImageWithURL方法中实现;
在这个方法中,首先通过调用SDImageCache的queryCacheOperationForKey方法去查询URL在缓存中的图片。
这个URL在SDImageCache的memCache对应一个key,其value就是对应的内存缓存图片;
如果图片中
但是当没有从内存缓存或者磁盘映像中获取到图片,那么就要从网络中异步下载图片。下载图片的网络请求任务是添加在 SDWebImageDownloaderOperation中的。SDWebImageDownloaderOperation继承自 NSOperation。这些操作SDWebImageDownloaderOperation依次存在 NSOperationQueue中。
其中这个添加任务到队列的操作进行了加锁。
因此说,SDWebImage是一个异步图片加载器。
3、带有自动缓存过期处理的异步内存+磁盘图片缓存机制;
SDWebImage的缓存周期是一周,也就是 60 * 60 * 24 * 7秒。
在进入后台时或者应用被杀死时,会进行判断:如果超过了缓存周期,就会删除URL所对应的文件;
图片下载完成后,将图片存在缓存中,再根据根据配置项选择是否将图片存储到磁盘中。