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<SDWebImageDownloaderOperation> *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代理方法,接收下載的數據

圖片編解碼
有時間在搞

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容