【无限互联】SDWebImage图片缓存流程分析

SDWebImage是一个功能很强大的缓存网络图片的框架。框架实现了异步加载网络图片、自动缓存图片数据等功能。以UIImageView加载网络图片为例,对其总体的加载图片流程做一个大致的分析。 首先使用SDWebImage先要导入 #import "UIImageView+WebCache.h"文件,设置网络图片的图片地址就可以加载图片。

NSURL *url = [NSURL URLWithString:@"http://b.hiphotos.baidu.com/imag1e03d003478ec54e736d196f9.jpg"]; 
[imageView setImageWithURL:url];


根据网络图片地址,SDWebImageManager类提供了方法downloadWithURL加载图片

id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadWithURL:url options:options progress:progressBlock completed:^(UIImage *image,  NSError *error, SDImageCacheType cacheType,  BOOL
if (!wself)  return; 
dispatch_main_sync_safe(^{ 
if (!wself)  return; 
if
wself.image = image; 
[wself setNeedsLayout]; 
} 
if
completedBlock(image, error, cacheType); 
} 
}); 
}]; 
objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 

进入downloadWithURL方法,由SDImagerCache类提供方法queryDiskCacheForKey检查内存中是否有图片缓存,如果有图片缓存,回调block将图片数据传递给SDWebImageManger类。SDWebImageMange类回调block将图片数据传递给UIImageView+WebCache类去显示图片。

UIImage *image = [self imageFromMemoryCacheForKey:key]; 
if
doneBlock(image, SDImageCacheTypeMemory); 
return nil; 
}

如果内存中没有图片缓存,将会去磁盘中查找图片缓存。这一步操作是异步操作,如果从磁盘中读取到图片数据,将图片数据添加到内存缓存中,回调block将图片数据传递给SDWebImageManger类。 SDWebImageMange类回调block将图片数据传递给UIImageView+WebCache类去显示图片

dispatch_async(self.ioQueue, ^{ 
if
return; 
} 

@autoreleasepool { 
UIImage *diskImage = [self diskImageForKey:key]; 
if
CGFloat cost = diskImage.size.height * diskImage.size.width * diskImage.scale; 
[self.memCache setObject:diskImage forKey:key cost:cost]; 
} 

dispatch_async(dispatch_get_main_queue(), ^{ 
doneBlock(diskImage, SDImageCacheTypeDisk); 
}); 
} 

内存和磁盘中都没有图片缓存,由SDWebImageDownloader类downloadImageWithURL方法请求网络下载图片。

- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(void (^)(NSInteger, NSInteger))progressBlock completed:(void (^)(UIImage *, NSData *, NSError *, BOOL))completedBlock { 
} 

图片下载完成后,数据下载完成后交给 SDWebImageDecoder 做图片解码处理,图片解码完成后回调给SDWebImageDownloader类,SDWebImageDownloader类,回调block将图片数据传递给SDWebImageManger类。 SDWebImageMange类回调block将图片数据传递给UIImageView+WebCache类显示图片。
图片数据会写入到内存和磁盘缓存中。图片数据写入磁盘缓存中是异步操作,避免拖慢主线程。

- (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk { 
if
return; 
} 
[self.memCache setObject:image forKey:key cost:image.size.height * image.size.width * image.scale]; 
if
dispatch_async(self.ioQueue, ^{ 
NSData

if
BOOL imageIsPng =  YES; 
if ([imageData length] >= [kPNGSignatureData length]) { 
imageIsPng = ImageDataHasPNGPreffix(imageData); 
} 
if
data = UIImagePNGRepresentation(image); 
} 
else { 
data = UIImageJPEGRepresentation(image, (CGFloat)1.0); 
} 
data = [NSBitmapImageRep representationOfImageRepsInArray:image.representations usingType: NSJPEGFileType properties:nil]; 
} 
if
if (![_fileManager fileExistsAtPath:_diskCachePath]) { 
[_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL]; 
} 
[_fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil]; 
} 
}); 
} 
}


总结:

1、SDWebImageManager *manager = [SDWebImageManager sharedManager];管理图片的加载,由SDImagerCache类检查内存中是否有图片缓存,或者由SDWebImageDownloader类请求网络下载图片。


2、SDImageCache 类管理图片缓存,读取图片缓存和写入图片缓存。


3、SDWebImageDownloader,根据URL向网络读取数据。