iOS--SDWebImage處理流程隨筆

首先附上git地址:https://github.com/SDWebImage/SDWebImage

附上SDWebImage類圖:

SDWebImageClassDiagram.png

附上SDWebImage步驟圖:

SDWebImageSequenceDiagram.png

核心模塊三部分:

1.主要調(diào)度類:SDWebImageManager;全部操作都是圍繞它為中心;
2.主要緩存類:SDImageCache;
3.主要下載類:SDWebImageDownload;

次要:

4.和UIView相關(guān)的類,是對UIKit的擴展,只是方便我們調(diào)起Manager里面的功能類;
5.SDImageCacheConfig用于配置緩存;

問題一,SD的大概流程:

1.通過UIImageView+WebCache作為入口,有placeholderImage的情況下,先顯示占位圖;
2.通過系統(tǒng)類NSMapTable判斷當(dāng)前是否有任務(wù)在執(zhí)行;
??3.重要步驟,如圖:

核心方法

問題二,內(nèi)存緩存模塊的實現(xiàn)步驟:

1.SDWebImage實現(xiàn)了磁盤,內(nèi)存雙緩存;
2.內(nèi)存緩存如何實現(xiàn)的:通過SDMemoryCache類來管理;
3.通過shouldUseWeakMemoryCache的Bool值,來判斷是否開啟內(nèi)存緩存;
4.內(nèi)存緩存有可能存在兩份,NSCache和SDMemoryCache,因為NSCache不可控;

問題三,磁盤模塊的實現(xiàn)步驟:

1.創(chuàng)建一個目錄;
2.為每一個緩存文件生成一個MD5文件名;
3.首先檢查內(nèi)存緩存,再檢查磁盤緩存,核心代碼:

- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options context:(nullable SDWebImageContext *)context done:(nullable SDImageCacheQueryCompletionBlock)doneBlock {
    if (!key) {
        if (doneBlock) {
            doneBlock(nil, nil, SDImageCacheTypeNone);
        }
        return nil;
    }
    
    id<SDImageTransformer> transformer = context[SDWebImageContextImageTransformer];
    if (transformer) {
        // grab the transformed disk image if transformer provided
        NSString *transformerKey = [transformer transformerKey];
        key = SDTransformedKeyForKey(key, transformerKey);
    }
    
    // First check the in-memory cache...
    //首先檢查內(nèi)存緩存…
    UIImage *image = [self imageFromMemoryCacheForKey:key];

    if ((options & SDImageCacheDecodeFirstFrameOnly) && image.sd_isAnimated) {
#if SD_MAC
        image = [[NSImage alloc] initWithCGImage:image.CGImage scale:image.scale orientation:kCGImagePropertyOrientationUp];
#else
        image = [[UIImage alloc] initWithCGImage:image.CGImage scale:image.scale orientation:image.imageOrientation];
#endif
    }

    BOOL shouldQueryMemoryOnly = (image && !(options & SDImageCacheQueryMemoryData));
    if (shouldQueryMemoryOnly) {
        if (doneBlock) {
            doneBlock(image, nil, SDImageCacheTypeMemory);
        }
        return nil;
    }
    
    // Second check the disk cache...
    //第二,檢查磁盤緩存…
    NSOperation *operation = [NSOperation new];
    // Check whether we need to synchronously query disk
    // 1. in-memory cache hit & memoryDataSync
    // 2. in-memory cache miss & diskDataSync
    BOOL shouldQueryDiskSync = ((image && options & SDImageCacheQueryMemoryDataSync) ||
                                (!image && options & SDImageCacheQueryDiskDataSync));
    void(^queryDiskBlock)(void) =  ^{
        if (operation.isCancelled) {
            // do not call the completion if cancelled
            return;
        }
        
        @autoreleasepool {
            NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key];
            UIImage *diskImage;
            SDImageCacheType cacheType = SDImageCacheTypeNone;
            if (image) {
                // the image is from in-memory cache, but need image data
                diskImage = image;
                cacheType = SDImageCacheTypeMemory;
            } else if (diskData) {
                cacheType = SDImageCacheTypeDisk;
                // decode image data only if in-memory cache missed
                diskImage = [self diskImageForKey:key data:diskData options:options context:context];
                if (diskImage && self.config.shouldCacheImagesInMemory) {
                    NSUInteger cost = diskImage.sd_memoryCost;
                    [self.memCache setObject:diskImage forKey:key cost:cost];
                }
            }
            
            if (doneBlock) {
                if (shouldQueryDiskSync) {
                    doneBlock(diskImage, diskData, cacheType);
                } else {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        doneBlock(diskImage, diskData, cacheType);
                    });
                }
            }
        }
    };
    
    // Query in ioQueue to keep IO-safe
    if (shouldQueryDiskSync) {
        dispatch_sync(self.ioQueue, queryDiskBlock);
    } else {
        dispatch_async(self.ioQueue, queryDiskBlock);
    }
    
    return operation;
}

問題四,下載模塊的實現(xiàn)步驟:

1.SDWebImageDownloader實現(xiàn)了下載管理;圍繞NSURLSession實現(xiàn)的;
2.SDWebImageDownloaderOperation實現(xiàn)了生命周期管理,具體任務(wù)是它來實現(xiàn)的;
3.核心方法SDWebImageDownloader里的:

- (nullable NSOperation<SDWebImageDownloaderOperation> *)createDownloaderOperationWithUrl:(nonnull NSURL *)url
                                                                                  options:(SDWebImageDownloaderOptions)options
                                                                                  context:(nullable SDWebImageContext *)context {
...
}

4.SDWebImageDownloaderConfig里,SDWebImageDownloaderExecutionOrder枚舉,兩種情況:

/// Operation execution order
typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
    /**
     * Default value. All download operations will execute in queue style (first-in-first-out).
     */
    SDWebImageDownloaderFIFOExecutionOrder,
    
    /**
     * All download operations will execute in stack style (last-in-first-out).
     */
    SDWebImageDownloaderLIFOExecutionOrder
};

FIFOE為先進先出,LIFOE為后進先出;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容