好的,下面我们将更详细地分析 SDWebImage 的源码,结合关键代码段来深入了解其设计和实现。
1. SDWebImageManager
SDWebImageManager 是整个库的核心类,负责管理图片的下载和缓存。
核心方法 loadImageWithURL:options:progress:completed::
- (nullable SDWebImageCombinedOperation *)loadImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
progress:(nullable SDImageLoaderProgressBlock)progressBlock
completed:(nullable SDInternalCompletionBlock)completedBlock {
// 校验 URL
if (!url || !completedBlock) {
if (completedBlock) {
completedBlock(nil, nil, SDImageCacheTypeNone, NSURLResponse *response, SDWebImageErrorInvalidURL, YES, url);
}
return nil;
}
// 创建一个 operation 对象
__block SDWebImageCombinedOperation *operation = [SDWebImageCombinedOperation new];
__weak SDWebImageCombinedOperation *weakOperation = operation;
// 获取缓存的 key
NSString *key = [self cacheKeyForURL:url];
// 查询缓存
operation.cacheOperation = [self.imageCache queryImageForKey:key
options:options
context:context
completion:^(UIImage * _Nullable cachedImage, NSData * _Nullable cachedData, SDImageCacheType cacheType) {
// 如果缓存命中,则直接调用完成回调并返回
if (cachedImage) {
[self callCompletionBlockForOperation:weakOperation
completion:completedBlock
image:cachedImage
data:cachedData
error:nil
cacheType:cacheType
finished:YES
url:url];
[self safelyRemoveOperationFromRunning:operation];
return;
}
// 如果缓存没有命中,则进行下载
// ...
}];
return operation;
}
2. SDWebImageDownloader
SDWebImageDownloader 使用 NSURLSession 进行图片的下载。
核心方法 downloadImageWithURL:options:progress:completed::
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
options:(SDWebImageDownloaderOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock {
// 校验 URL
if (!url) {
if (completedBlock) {
completedBlock(nil, nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:nil]);
}
return nil;
}
// 创建一个下载操作
SDWebImageDownloaderOperation *operation = [[SDWebImageDownloaderOperation alloc] initWithRequest:request];
// 配置下载操作的回调
operation.progressBlock = progressBlock;
operation.completedBlock = completedBlock;
// 将下载操作添加到队列中
[self.downloadQueue addOperation:operation];
return operation;
}
3. SDImageCache
SDImageCache 负责图片的缓存管理,包含内存缓存和磁盘缓存。
核心方法 queryImageForKey:options:completion::
- (nullable NSOperation *)queryImageForKey:(nullable NSString *)key
options:(SDImageCacheOptions)options
completion:(nullable SDImageCacheCompletionBlock)completionBlock {
if (!key) {
if (completionBlock) {
completionBlock(nil, nil, SDImageCacheTypeNone);
}
return nil;
}
// 首先查询内存缓存
UIImage *image = [self.memoryCache objectForKey:key];
if (image) {
if (completionBlock) {
completionBlock(image, nil, SDImageCacheTypeMemory);
}
return nil;
}
// 如果内存缓存没有命中,则查询磁盘缓存
NSOperation *operation = [self.diskCache queryDiskCacheForKey:key done:^(UIImage * _Nullable diskImage, NSData * _Nullable data) {
if (completionBlock) {
completionBlock(diskImage, data, SDImageCacheTypeDisk);
}
}];
return operation;
}
4. UIImageView+WebCache
这个分类为 UIImageView 提供了方便的方法来加载网络图片。
核心方法 sd_setImageWithURL:placeholderImage:options:progress:completed::
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
progress:(nullable SDImageLoaderProgressBlock)progressBlock
completed:(nullable SDInternalCompletionBlock)completedBlock {
// 取消当前的图像加载
[self sd_cancelCurrentImageLoad];
// 设置占位图
self.image = placeholder;
if (url) {
// 使用 SDWebImageManager 加载图片
__weak typeof(self) wself = self;
id <SDWebImageOperation> operation = [self.sd_imageManager loadImageWithURL:url
options:options
progress:progressBlock
completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
if (!wself) return;
dispatch_main_async_safe(^{
if (!wself) return;
if (image) {
wself.image = image;
[wself setNeedsLayout];
}
if (completedBlock && finished) {
completedBlock(image, data, error, cacheType, finished, imageURL);
}
});
}];
// 将操作与 UIImageView 绑定
[self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
}
}
总结
通过源码分析,可以看出 SDWebImage 采用了模块化的设计,每个组件职责明确。SDWebImageManager 负责管理图片的下载和缓存,SDWebImageDownloader 进行图片的下载操作,SDImageCache 负责图片的缓存管理,而 UIImageView+WebCache 则提供了便捷的接口供开发者调用。
这种设计使得 SDWebImage 不仅易于使用,而且便于维护和扩展。开发者可以根据需要自定义缓存策略、下载选项等,从而灵活地处理各种图片加载需求。