SDWebImage
https://www.jianshu.com/p/b3eff8304b37
https://www.jianshu.com/p/a33d5abf686b
SDWebImage
|—-SDWebImageCompat
处理不同平台(iOS、TV、OS、Watch)宏,以及根据文件名@2x、@3x进行图片处理和缩放
|—-SDWebImageOperation.h 添加cancel的delegate
+—-Cache
|——–SDImageCache 主要处理缓存逻辑,重点集中在:NSCache(Memory)、Disk读写、清理Old File
|——–SDImageCacheConfig
配置缓存参数:是否压缩、iCloud、InMemory、ReadingOption、时间和CacheSize
+—-Downloader
|——–SDWebImageDownloaderOperation 主要提供下载的Operation操作
|——–SDWebImageDownloader 提供下载管理入口
+—-Utils
|——–SDWebImageManager 提供外层管理cache和download入口
|——–SDWebImagePrefetcher 预处理获取Image,主要应用预加载的地方
+—-Categories
|——–NSData+ImageContentType 提供类型判断和ImageIO类型转换
|——–UIImage+GIF Data转UIImage(GIF)扩展
|——–UIImage+MultiFormat 提供BitMap或者未知类型的Data转UIImage扩展
|——–UIImage+WebP Data转WebP扩展
|——–UIImage+ForceDecode 解压操作
|——–UIView+WebCacheOperation 提供顶层关于取消和下载记录的扩展
+—-Decoder
|——–SDWebImageCodersManager 整体Coders的入口,提供是否可Coder和Coder转发
|——–SDWebImageCoder 主要说明Coder Delegate 需要实现的接口
|——–SDWebImageImageIOCoder PNG/JPEG的Encode和解压操作
|——–SDWebImageGIFCoder GIF的Coder操作
|——–SDWebImageWebPCoder WebP的Coder操作
|——–SDWebImageFrame 辅助类,主要在GIF等动态图使用
|——–SDWebImageCoderHelper 辅助类,包括方向、Gif图合成等
整体组件结构
1、缓存部分解析
缓存部分逻辑主要是在SDImageCache,包括如下几个方面:
新增
删除
查询
缓存管理(过期)
SDWebImage的缓存中,主要走了一套NSCache管理内存和根据传入的Key转换MD5作为文件名存储。以及创建了一个IO操作的Queue进行管理IO操作。
这里重点注意,任何耗时:包括IO读写、转码等操作,都不应该放到主线程里面使用。
1、通过NSOperation管理queue任务
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock {
if (!key) {
if (doneBlock) {
doneBlock(nil, nil, SDImageCacheTypeNone);
}
return nil;
}
// First check the in-memory cache...
UIImage *image = [self imageFromMemoryCacheForKey:key];
if (image) {
NSData *diskData = nil;
if (image.images) {
diskData = [self diskImageDataBySearchingAllPathsForKey:key];
}
if (doneBlock) {
doneBlock(image, diskData, SDImageCacheTypeMemory);
}
return nil;
}
NSOperation *operation = [NSOperation new];
dispatch_async(self.ioQueue, ^{
if (operation.isCancelled) {
// do not call the completion if cancelled
return;
}
@autoreleasepool {
NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key];
UIImage *diskImage = [self diskImageForKey:key];
if (diskImage && self.config.shouldCacheImagesInMemory) {
NSUInteger cost = SDCacheCostForImage(diskImage);
[self.memCache setObject:diskImage forKey:key cost:cost];
}
if (doneBlock) {
dispatch_async(dispatch_get_main_queue(), ^{
doneBlock(diskImage, diskData, SDImageCacheTypeDisk);
});
}
}
});
return operation;
}
查询缓存的时候,这里采用了NSOperation进行是否取消的操作,因为当下载/缓存内容过多时,毕定存在先后处理顺序的问题,这时候可能由于用户操作等需要取消当前缓存处理,那么 NSOperation 这里起的唯一作用就是提供取消操作。可以参考具体的Manager里面缓存调起逻辑。