说白了,这个框架是一个异步下载图片并且支持缓存的 UIImageView 分类
原理图如下:
最常使用的是这个方法
[self.imageView sd_setImageWithURL:[NSURL URLWithString:@"url"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
首先我们来以UIImageView+WebCache中- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
这个方法为入口研究SDWebImage是如何工作的.
当我们进入到.m实现文件的时候如下
发现这个方法唯一的作用就是调用了另一个方法
[self sd_setImageWithURL:placeholderImage:options:progress:completed:]
其实仔细看看暴露给我们使用的方法后,不难看出,最终都会调用这个方法,只是根据需要传入的参数不同而已,无疑这是UIImageView+WebCache中的核心方法
这个方法具体实现代码比较多,大家点击头文件都可以看到
操作管理
方法的第一行代码是
[self sd_cancelCurrentImageLoad];
这是整个框架管理操作队列的方法,写这个方法是取消当前正在进行中的下载(实际上没有下载),防止与即将进行的操作发生冲突.会调用:
[self sd_cancelImageLoadOperationWithKey:@"UIImageViewImageLoad"]```
###占位图片
if (!(options & SDWebImageDelayPlaceholder)) {
self.image = placeholder;
}
默认情况下options == 0,那么会为当前的UIImageView添加一个临时的image,也就是占位图.
####获取图片
接下来会检测传入的url是否为空,非空全局SDWebImageView会调用以下方法获取图片
[SDWebImageManager.sharedManager downloadImageWithURL:options:progress:completed:]
下载完后会调用```(SDWebImageCompletionWithFinishedBlock)completedBlock```为UIImageView.image赋值,添加上最终所需要的图片
dispatch_main_sync_safe(^{
if (!wself) return;
if (image) {
wself.image = image;
[wself setNeedsLayout];
} else {
if ((options & SDWebImageDelayPlaceholder)) {
wself.image = placeholder;
[wself setNeedsLayout];
}
}
if (completedBlock && finished) {
completedBlock(image, error, cacheType, url);
}
});
接下来分析SDWebImageManager中的方法
[SDWebImageManager.sharedManager downloadImageWithURL:options:progress:completed:]
####SDWebImageManager
这个类是用来处理异步下载和图片缓存的类,
获取图片的过程有大体上分为两部分, 它首先会在 SDWebImageCache 中寻找图片是否有对应的缓存, 它会以 url 作为数据的索引先在内存中寻找是否有对应的缓存, 如果缓存未命中就会在磁盘中利用 MD5 处理过的 key 来继续查询对应的数据, 如果找到了, 就会把磁盘中的缓存备份到内存中.
然而, 假设我们在内存和磁盘缓存中都没有命中, 那么 manager 就会调用它持有的一个 SDWebImageDownloader 对象的方法 downloadImageWithURL:... 来下载图片, 这个方法会在执行的过程中调用另一个方法 addProgressCallback:andCompletedBlock:forURL:createCallback: 来存储下载过程中和下载完成的回调, 当回调块是第一次添加的时候, 方法会实例化一个 NSMutableURLRequest 和 SDWebImageDownloaderOperation, 并将后者加入 downloader 持有的下载队列开始图片的异步下载.
而在图片下载完成之后, 就会在主线程设置 image 属性, 完成整个图像的异步下载和配置.
####总结
整个框架的图片加载过程其实很符合我们常人的逻辑
查看缓存:
a)查看内存中(程序可能已经加载过这个图片)是否有缓存,如果有就返回图片设置图片;没有就查看磁盘缓存,有就返回图片并设置
b)内存和磁盘中都没有缓存,网络异步下载图片,加入磁盘缓存和内存缓存,设置图片