1、类图

2、时序图

3、目录结构
Downloader
- SDWebImageDownloader 下载图片优化图片加载
- SDWebImageDownloaderOperation 继承NSOperation,用来处理下载任务的
Cache
- SDImageCache 用来处理内存缓存和磁盘缓存的,其中磁盘缓存是异步进行的,不会阻塞主线程
Utils
- SDWebImageManager 将图片下载(SDWebImageDownloader)和图片缓存(SDImageCache)两个独立的功能组合起来
- SDWebImageDecoder 图片解码器,用于图片下载完成后进行解码
- SDWebImagePrefetcher 预下载图片
Categories
- UIView+WebCacheOperation 用来记录图片加载的operation,方便需要时取消和移除图片加载的operation
- UIImageView+WebCache 集成SDWebImageManager的图片下载和缓存功能到UIImage的方法中,方便使用
- UIImageView+HighlightedWebCache
- UIButton +WebCache
- NSData+ImageContentType 用于获取图片数据的格式(jpeg png等)
- UIImage+GIF 用于加载GIF动图
- UIImage+MultiFormat 根据不同格式的二进制数据转成UIImage对象
Other
- SDWebImageOperation 协议 只有一个方法cancel
- SDWebImageCompat 宏定义、常量、通用函数
4、流程
[imageView sd_setImageWithURL:url placeholderImage:placeholderImage]
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock {
[self sd_cancelCurrentImageLoad];
objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if (!(options & SDWebImageDelayPlaceholder)) {
dispatch_main_async_safe(^{
self.image = placeholder;
});
}
if (url) {
// check if activityView is enabled or not
if ([self showActivityIndicatorView]) {
[self addActivityIndicator];
}
__weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
[wself removeActivityIndicator];
if (!wself) return;
dispatch_main_sync_safe(^{
if (!wself) return;
if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock)
{
completedBlock(image, error, cacheType, url);
return;
}
else if (image) {
wself.image = image;
[wself setNeedsLayout];
} else {
if ((options & SDWebImageDelayPlaceholder)) {
wself.image = placeholder;
[wself setNeedsLayout];
}
}
if (completedBlock && finished) {
completedBlock(image, error, cacheType, url);
}
});
}];
[self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
} else {
dispatch_main_async_safe(^{
[self removeActivityIndicator];
if (completedBlock) {
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
completedBlock(nil, error, SDImageCacheTypeNone, url);
}
});
}
}
经过层层调用,直到 UIImageView+WebCache 中最核心的方法 sd_setImageWithURL: placeholderImage: options: progress: completed: 该方法中,主要做了以下几件事:
- [self sd_cancelCurrentImageLoad];取消当前正在进行的加载任务operation
- self.image = placeholder;设置placeholder
- 如果url不为nil,就通过SDWebImageManager单例开启图片加载任务operation,SDWebImageManager的图片加载方法中会返回一个SDWebImageCombineOperation对象,这个对象包含一个cacheOperation和一个cancelBlock。
SDWebImageManager 的图片加载方法 downloadImageWithURL:options:progress:completed: 中
- 会先拿图片缓存的 key (这个 key 默认是图片 URL)去 SDImageCache 中读取内存缓存,如果有,就返回给 SDWebImageManager;
- 如果内存缓存没有,就开启异步线程,拿经过 MD5 处理的 key 去读取磁盘缓存,如果找到磁盘缓存了,就同步到内存缓存中去,然后再返回给 SDWebImageManager。
- 如果内存缓存和磁盘缓存中都没有,SDWebImageManager 就会调用 SDWebImageDownloader 单例的 -downloadImageWithURL: options: progress: completed: 方法去下载,该会先将传入的 progressBlock 和 completedBlock 保存起来,并在第一次下载该 URL 的图片时,创建一个 NSMutableURLRequest 对象和一个 SDWebImageDownloaderOperation 对象,并将该 SDWebImageDownloaderOperation 对象添加到 SDWebImageDownloader 的downloadQueue 来启动异步下载任务。
SDWebImageDownloaderOperation 中包装了一个 NSURLConnection 的网络请求,并通过 runloop 来保持 NSURLConnection 在 start 后、收到响应前不被干掉,下载图片时,监听 NSURLConnection 回调的 -connection:didReceiveData: 方法中会负责 progress 相关的处理和回调,- connectionDidFinishLoading: 方法中会负责将 data 转为 image,以及图片解码操作,并最终回调 completedBlock。
SDWebImageDownloaderOperation 中的图片下载请求完成后,会回调给 SDWebImageDownloader,然后 SDWebImageDownloader 再回调给 SDWebImageManager,SDWebImageManager 中再将图片分别缓存到内存和磁盘上(可选),并回调给 UIImageView,UIImageView 中再回到主线程设置 image 属性。至此,图片的下载和缓存操作就结束了。
SDWebImage使用LRU缓存淘汰算法。缓存有效期默认是7天。
网友评论