SDWebImage梳理

加载流程

围绕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是系统缓存,不受我们控制,可能会被随时清空.

磁盘缓存

  1. 创建目录
  2. 为每一个文件生成一个MD5文件名
  3. 清除磁盘缓存
  • 删除超过截至日期的文件
  • 按访问或修改日期排序删除更早的文件

下载模块

创建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];时,自动执行operationstart方法,[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代理方法,接收下载的数据

图片编解码
有时间在搞

你可能感兴趣的:(SDWebImage梳理)