一、 通过 FLAnimatedImageView 、UIImageView、UIView、UIButton 调用sd_setImageWithURL...实现网络图片异步加载,缓存等功能,
demo:
FLAnimatedImageView *customImageView = [[FLAnimatedImageView alloc] initWithFrame:CGRectMake(0,0,100,100)];
[customImageView sd_setImageWithURL:[NSURL URLWithString:url]
placeholderImage:placeholderImage
options:SDWebImageRefreshCached];
二、 代码解析
1. FlanimatedImageView+WebCache
调用 UIVIew+WebCache 中 sd_internalSetImageWithURL
2. UIVIew+WebCache
调用 SDWebImageManager loadImageWithURL,完成后设置image或者调用completeBlock;
3. SDWebImageManager - loadImageWithURL
a. 对错误url 并且没有非重试标记的直接返回,避免多次失败;
b. 创建 SDWebImageCombinedOperation,添加到 runingOperations 中;
c. 调用 SDImageCahe 的 queryCacheOperationForKey 查找cache;
d. 有cache,返回结果,从runingOperations 中remove 掉operation;
e. 没有cache,调用SDWebImageDownloader 的downloadImageWithURL 下载;
f. 下载成功缓存,返回;失败返回;
4. SDImageCache - queryCacheOperationForKey
a. 分别从内存缓存、本地缓存读取(本地读取后,需要解码),并返回一个NSOperation;
5. SDWebImageDownloader - downloadImageWithURL
a. 创建 SDWebImageDownloaderOperation,包含 NSMUtableURLRequest 和 NSURLSession;添加到 downloadQueue中;
b. 以url 为key, operation 为value 保存到 URLOperations;
c. 创建 SDWebImageDownloadToken , 把url , cancelToken 赋值给该变量;
7. SDWebImageDownloaderOperation - start
生成dataTask;执行 [self.dataTask resume];
8. SDWebImageDownloader 收到 NSURLSessionTaskDelegate、NSURLSessionDataDelegate 代理后,
查找SDWebImageDownloaderOperation 并且调用响应 方法;
9. SDWebImageDownloaderOperation 下载代理
a. 接收数据添加到 imageData 中;
b. 下载完成后 通过 imageData 生成UIImage,如果需要解码生成UIImage,返回;
三、同步机制
1. SDImageCache
dispatch_queue_t ioQueue = dispatch_queue_create("com.hackemist.SDWebImageCache", DISPATCH_QUEUE_SERIAL);
读取本地文件,设置缓存时,通过串行队列保证缓存io的同步机制;
2. SDWebImageDownloader
dispatch_queue_t _barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_barrier_async (self.barrierQueue, ^ { …});
添加、删除operation 时,通过dispatch_barrier_async 来保证同步;
3. SDWebImageDownloaderOperation
_barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderOperationBarrierQueue", DISPATCH_QUEUE_CONCURRENT);
对callback 实现多个读和1个写的同步机制;
dispatch_sync(self.barrierQueue, ^{…});
dispatch_barrier_async(self.barrierQueue …);