SDWebImage源碼解讀(二)

今天總計(jì)一下SDWebImage核心模塊之下載模塊。下載模塊主要包括兩個(gè)類SDWebImageDownloader和SDWebImageDownloaderOperation。其中SDWebImageDownloader負(fù)責(zé)對(duì)所有下載任務(wù)的管理,SDWebImageDownloaderOperation負(fù)責(zé)具體的一個(gè)下載任務(wù)的執(zhí)行。另外為了拓展下載功能,還支持實(shí)現(xiàn)SDWebImageDownloaderOperationInterface協(xié)議來(lái)自定義SDWebImageDownloaderOperation,根據(jù)需求自定義下載行為。

SDWebImageDownloader內(nèi)部構(gòu)成

SDWebImageDownloader內(nèi)部持有一個(gè)下載隊(duì)列downloadQueue用于管理所有下載操作,一個(gè)緩存字典緩存所有的SDWebImageDownloaderOperation下載操作,一個(gè)httpheader的設(shè)置字典設(shè)置下載的請(qǐng)求頭信息,兩個(gè)信號(hào)鎖保證緩存字典和header頭字典的安全操作。同時(shí)持有一個(gè)下載的session和下載session的對(duì)應(yīng)的配置文件NSURLSessionConfiguration。

SDWebImageDownloader主要方法

- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
                                                   options:(SDWebImageDownloaderOptions)options
                                                  progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
                                                 completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock {
    __weak SDWebImageDownloader *wself = self;

    return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^SDWebImageDownloaderOperation *{
         __strong __typeof (wself) sself = wself;
        NSTimeInterval timeoutInterval = sself.downloadTimeout;
        if (timeoutInterval == 0.0) {
            timeoutInterval = 15.0;
        }

        // In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise
      //NSURLRequest生成
        NSURLRequestCachePolicy cachePolicy = options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url
                                                                    cachePolicy:cachePolicy
                                                                timeoutInterval:timeoutInterval];
        //設(shè)置cookie信息
        request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies);
        request.HTTPShouldUsePipelining = YES;
        //設(shè)置header信息
        if (sself.headersFilter) {
            request.allHTTPHeaderFields = sself.headersFilter(url, [sself allHTTPHeaderFields]);
        }
        else {
            request.allHTTPHeaderFields = [sself allHTTPHeaderFields];
        }
        //組建SDWebImageDownloaderOperation
        SDWebImageDownloaderOperation *operation = [[sself.operationClass alloc] initWithRequest:request inSession:sself.session options:options];
        operation.shouldDecompressImages = sself.shouldDecompressImages;
        //設(shè)置加密信息
        if (sself.urlCredential) {
            operation.credential = sself.urlCredential;
        } else if (sself.username && sself.password) {
            operation.credential = [NSURLCredential credentialWithUser:sself.username password:sself.password persistence:NSURLCredentialPersistenceForSession];
        }
        //設(shè)置優(yōu)先級(jí)
        if (options & SDWebImageDownloaderHighPriority) {
            operation.queuePriority = NSOperationQueuePriorityHigh;
        } else if (options & SDWebImageDownloaderLowPriority) {
            operation.queuePriority = NSOperationQueuePriorityLow;
        }
        //設(shè)置隊(duì)列
        if (sself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
            // Emulate LIFO execution order by systematically adding new operations as last operation's dependency
            [sself.lastAddedOperation addDependency:operation];
            sself.lastAddedOperation = operation;
        }

        return operation;
    }];
}

此方法用于對(duì)外的暴露,實(shí)際上進(jìn)行了SDWebImageDownloaderOperation的生成的相關(guān)設(shè)置工作。NSURLRequest生成并設(shè)置的header信息、cookie信息設(shè)置。NSURLRequest、session、配置options生成DownloaderOperation. DownloaderOperation設(shè)置加密、優(yōu)先級(jí)、隊(duì)列。最后通過(guò)addProgressCallback方法將operation緩存,并添加到操作隊(duì)列中addOperation。

SDWebImageDownloader下載選項(xiàng)

SDWebImageDownloader提供了很多下載選項(xiàng),可以根據(jù)情況進(jìn)行配置。如設(shè)置下載優(yōu)先級(jí)、進(jìn)度、后臺(tái)下載,圖片縮放等,同時(shí)支持先進(jìn)先出,先進(jìn)后出的下載方式。

typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
    //下載低優(yōu)先級(jí)
    SDWebImageDownloaderLowPriority = 1 << 0,
    //下載高優(yōu)先級(jí)
    SDWebImageDownloaderHighPriority = 1 << 7,
    // 帶有進(jìn)度
    SDWebImageDownloaderProgressiveDownload = 1 << 1,
    //默認(rèn)不使用URLCache
    SDWebImageDownloaderUseNSURLCache = 1 << 2,
    //如果圖片是在NSURLCAche中讀取時(shí),調(diào)用completion block時(shí),返回nil,配合SDWebImageDownloaderUseNSURLCache使用
    SDWebImageDownloaderIgnoreCachedResponse = 1 << 3,
    //支持后臺(tái)下載
    SDWebImageDownloaderContinueInBackground = 1 << 4,
    //支持NSHTTPCookieStore的cookie信息,進(jìn)而設(shè)置NSMutableURLRequest.HTTPShouldHandleCookies=YES
    SDWebImageDownloaderHandleCookies = 1 << 5,
    //允許不信任SSL證書(shū)
    SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6,
    //縮放大圖片
    SDWebImageDownloaderScaleDownLargeImages = 1 << 8,
};

typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
     //先進(jìn)先出
    SDWebImageDownloaderFIFOExecutionOrder,
    //先進(jìn)后出
    SDWebImageDownloaderLIFOExecutionOrder
};

SDWebImageDownloader默認(rèn)配置

1.解壓縮shouldDecompressImages:默認(rèn)情況下,圖片下載下來(lái)就解壓縮,這是拿空間換時(shí)間的做法,讓圖片在使用時(shí)能更快的加載。

2.最大下載數(shù)maxConcurrentDownloads:此屬性實(shí)質(zhì)是設(shè)置下載隊(duì)列(NSOperationQueue)的最大數(shù)并發(fā)數(shù)。

3.當(dāng)前最大下載數(shù)currentDownloadCount:當(dāng)前下載隊(duì)列中未執(zhí)行完畢的操作個(gè)數(shù)

4.下載超時(shí)時(shí)間downloadTimeout:默認(rèn)設(shè)置為15秒

5.下載隊(duì)列executionOrder:默認(rèn)是先進(jìn)先出,先到先下載的隊(duì)列

SDWebImageDownloaderOperation

SDWebImageDownloaderOperation持有NSURLSessionTask和NSURLRequest,在start方法中創(chuàng)建網(wǎng)絡(luò)請(qǐng)求并執(zhí)行,在URLSession:task:didCompleteWithError:中進(jìn)行數(shù)據(jù)的整合處理,反饋給外部。

總結(jié):

SDWebImage的下載管理模塊SDWebImageDownloader采用了NSOperationQueue來(lái)管理隊(duì)列,而沒(méi)有使用更加高效的GCD來(lái)完成。這是因?yàn)橄螺d的業(yè)務(wù)的復(fù)雜性比較高,如優(yōu)先級(jí)設(shè)置、取消操作、操作狀態(tài)的監(jiān)控、操作的依賴性,這些如果用GCD來(lái)封裝的話,最后的結(jié)果就是寫(xiě)出一個(gè)NSOperationQueue出來(lái),所以我猜作者肯定想何必再封裝造輪子呢,直接使用NSOperationQueue得了。

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

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

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