加载流程
围绕SDWebImageManager
sd_setImageWithURL()
--> sd_internalSetImageWithURL
//首先从self的任务operations:NSMapTable 中取消任务
[self sd_cancelImageLoadOperationWithKey:validOperationKey];
manager
--> loadImageWithURL
创建operation
SDWebImageCombinedOperation *operation = [SDWebImageCombinedOperation new];
operation.manager = self;
SD_LOCK(self.runningOperationsLock);
[self.runningOperations addObject:operation];
SD_UNLOCK(self.runningOperationsLock);
开始进入加载图片
// Start the entry to load image from cache
[self callCacheProcessForOperation:operation url:url options:options context:context progress:progressBlock completed:completedBlock];
开始查找缓存:内存查找 --> 硬盘查找
key: 可自定义cacheKeyFilter,默认url.absoluteString
// First check the in-memory cache...
UIImage *image = [self imageFromMemoryCacheForKey:key];
// Second check the disk cache...
NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key];
如果有缓存,加载缓存,如果需要刷新缓存,则继续请求网络
// If image was found in the cache but SDWebImageRefreshCached is provided, notify about the cached image
// AND try to re-download it in order to let a chance to NSURLCache to refresh it from server.
[self callCompletionBlockForOperation:operation completion:completedBlock image:cachedImage data:cachedData error:nil cacheType:cacheType finished:YES url:url];
operation = [self createDownloaderOperationWithUrl:url options:options context:context];
[self.downloadQueue addOperation:operation];
开始缓存
[self callStoreCacheProcessForOperation:operation url:url options:options context:context downloadedImage:downloadedImage downloadedData:downloadedData finished:finished progress:progressBlock completed:completedBlock];
缓存模块
缓存配置类:SDImageCacheConfig
-
shouldCacheImagesInMemory
是否允许内存缓存 -
shouldUseWeakMemoryCache
弱引用内存缓存,如果对象被释放,则缓存也释放 -
maxMemoryCount
缓存图片个数限制,默认0不限制 -
maxMemoryCost
最大内存占用空间,默认为0不限制,1 pixel is 4 bytes (32 bits)
内存缓存 SDMemoryCache
SDMemoryCache
继承自NSCache
,通过weakCache: NSMapTable
来缓存图片,NSMapTabel
对比NSDictionary
有更多内存语义(strong、weak、copy、assign)
self.weakCache = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];
value
弱引用,当图片被释放时,自动删除此key-value
- (void)setObject:(id)obj forKey:(id)key cost:(NSUInteger)g {
[super setObject:obj forKey:key cost:g];
if (!self.config.shouldUseWeakMemoryCache) {
return;
}
if (key && obj) {
// Store weak cache
SD_LOCK(self.weakCacheLock);
[self.weakCache setObject:obj forKey:key];
SD_UNLOCK(self.weakCacheLock);
}
}
内存缓存时会在NSCache
缓存一份,我们自定义的weakCache
中再缓存一份
//取出缓存
- (id)objectForKey:(id)key {
id obj = [super objectForKey:key];
if (!self.config.shouldUseWeakMemoryCache) {
return obj;
}
if (key && !obj) {
// Check weak cache
SD_LOCK(self.weakCacheLock);
obj = [self.weakCache objectForKey:key];
SD_UNLOCK(self.weakCacheLock);
if (obj) {
// Sync cache
NSUInteger cost = 0;
if ([obj isKindOfClass:[UIImage class]]) {
cost = [(UIImage *)obj sd_memoryCost];
}
[super setObject:obj forKey:key cost:cost];
}
}
return obj;
}
从NSCache
中取出缓存,在从weakCache
中取出缓存,并同步到NSCache
中
NSCache
是系统缓存,不受我们控制,可能会被随时清空.
磁盘缓存
- 创建目录
- 为每一个文件生成一个MD5文件名
- 清除磁盘缓存
- 删除超过截至日期的文件
- 按访问或修改日期排序删除更早的文件
下载模块
创建NSOperation
生成NSURLRequest,创建NSOperation
NSOperation *operation = [[operationClass alloc] initWithRequest:request inSession:self.session options:options context:context];
控制任务优先级,先进先出或者后进先出
if (self.config.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
// Emulate LIFO execution order by systematically adding new operations as last operation's dependency
[self.lastAddedOperation addDependency:operation];
self.lastAddedOperation = operation;
}
SDWebImageDownloaderOperation
重写了start
方法,当[self.downloadQueue addOperation:operation];
时,自动执行operation
的start
方法,[dataTask resume]
则开始下载任务
//如果session不存在则创建session
/**
* Create the session for this task
* We send nil as delegate queue so that the session creates a serial operation queue for performing all delegate
* method calls and completion handler calls.
*/
session = [NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:nil];
//生成dataTask
self.dataTask = [session dataTaskWithRequest:self.request];
//执行
[self.dataTask resume];
NSURLSessionDataDelegate
,NSURLSessionTaskDelegate
代理方法,接收下载的数据
图片编解码
有时间在搞