亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

SDWebImage 源碼閱讀(四)

2019-11-09 14:46:53
字體:
來源:轉載
供稿:網友

這一篇我們來解決最后的問題,使用 SDWebImage 中下載圖片的類 SDWebImageDownloader,這個類學習完以后,我們對 SDWebImage 的理解會更加深刻。

1. 下載圖片

- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options PRogress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock { __block SDWebImageDownloaderOperation *operation; __weak __typeof(self)wself = self; // 判斷是否為第一次下載,并且存儲 progressBlock 和 completedBlock,詳情見 1.1 [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^{ // 第一次下載回調用這個block中的代碼 // 圖片下載的超時時間 NSTimeInterval timeoutInterval = wself.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 // 創建請求 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:(options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData) timeoutInterval:timeoutInterval]; // HTTPShouldHandleCookies 為 YES 表示將 cookies 一起發送至服務器 request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies); // HTTPShouldUsePipelining 為 YES 可以極大的提高網絡性能,但是 HTTPShouldUsePipelining 也有其局限性,就是服務器必須按照收到請求的順序返回對應的數據 request.HTTPShouldUsePipelining = YES; // 設置頭文件 if (wself.headersFilter) { request.allHTTPHeaderFields = wself.headersFilter(url, [wself.HTTPHeaders copy]); } else { request.allHTTPHeaderFields = wself.HTTPHeaders; } // 詳情見 2. SDWebImageDownloaderOperation 核心類 operation = [[wself.operationClass alloc] initWithRequest:request insession:self.session options:options progress:^(NSInteger receivedSize, NSInteger expectedSize) { SDWebImageDownloader *sself = wself; if (!sself) return; __block NSArray *callbacksForURL; dispatch_sync(sself.barrierQueue, ^{ callbacksForURL = [sself.URLCallbacks[url] copy]; }); for (NSDictionary *callbacks in callbacksForURL) { dispatch_async(dispatch_get_main_queue(), ^{ SDWebImageDownloaderProgressBlock callback = callbacks[kProgressCallbackKey]; if (callback) callback(receivedSize, expectedSize); }); } } completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { SDWebImageDownloader *sself = wself; if (!sself) return; __block NSArray *callbacksForURL; dispatch_barrier_sync(sself.barrierQueue, ^{ callbacksForURL = [sself.URLCallbacks[url] copy]; if (finished) { [sself.URLCallbacks removeObjectForKey:url]; } }); for (NSDictionary *callbacks in callbacksForURL) { SDWebImageDownloaderCompletedBlock callback = callbacks[kCompletedCallbackKey]; if (callback) callback(image, data, error, finished); } } cancelled:^{ SDWebImageDownloader *sself = wself; if (!sself) return; dispatch_barrier_async(sself.barrierQueue, ^{ [sself.URLCallbacks removeObjectForKey:url]; }); }]; // 是否壓縮圖片 operation.shouldDecompressImages = wself.shouldDecompressImages; if (wself.urlCredential) { operation.credential = wself.urlCredential; } else if (wself.username && wself.passWord) { operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession]; } // 優先級 if (options & SDWebImageDownloaderHighPriority) { operation.queuePriority = NSOperationQueuePriorityHigh; } else if (options & SDWebImageDownloaderLowPriority) { operation.queuePriority = NSOperationQueuePriorityLow; } // 將 operation 加入隊列中 [wself.downloadQueue addOperation:operation]; if (wself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) { // Emulate LIFO execution order by systematically adding new operations as last operation's dependency // 如果為棧模式,需要添加依賴關系,棧頂完成才能執行下一個 operation [wself.lastAddedOperation addDependency:operation]; wself.lastAddedOperation = operation; } }]; return operation;}

1.1. 存儲 progressBlock 和 completedBlock

- (void)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL *)url createCallback:(SDWebImageNoParamsBlock)createCallback { // The URL will be used as the key to the callbacks dictionary so it cannot be nil. If it is nil immediately call the completed block with no image or data. if (url == nil) { if (completedBlock != nil) { completedBlock(nil, nil, nil, NO); } return; } // dispatch_barrier_sync : 等待在它前面的多線程執行完再執行這個 dispatch_barrier_sync(self.barrierQueue, ^{ // 判斷是否是第一次下載這個url,如果是第一次下載,將存儲該url BOOL first = NO; if (!self.URLCallbacks[url]) { self.URLCallbacks[url] = [NSMutableArray new]; first = YES; } // Handle single download of simultaneous download request for the same URL // 根據url從self.URLCallbacks字典中取出數組,將傳入的block根據兩個key(kProgressCallbackKey和kCompletedCallbackKey)copy到字典中 NSMutableArray *callbacksForURL = self.URLCallbacks[url]; NSMutableDictionary *callbacks = [NSMutableDictionary new]; if (progressBlock) callbacks[kProgressCallbackKey] = [progressBlock copy]; if (completedBlock) callbacks[kCompletedCallbackKey] = [completedBlock copy]; [callbacksForURL addObject:callbacks]; self.URLCallbacks[url] = callbacksForURL; if (first) { createCallback(); } });}

2. SDWebImageDownloaderOperation 核心類

在上面我們看到的下載圖片方法,并沒有涉及到核心代碼,原來是通過以下初始化來進入 SDWebImageDownloaderOperation 核心類

- (id)initWithRequest:(NSURLRequest *)request inSession:(NSURLSession *)session options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock cancelled:(SDWebImageNoParamsBlock)cancelBlock;

我們進入上面初始化方法的實現中看到,在 init 方法中只是對傳入參數的賦值和獲取,基本上是初始化內容,但是下面有個重寫的 start 方法

- (void)start { // 線程同步加鎖,重置 @synchronized (self) { if (self.isCancelled) { self.finished = YES; [self reset]; return; }#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 // 獲取系統的 application Class UIApplicationClass = NSClassFromString(@"UIApplication"); BOOL hasApplication = UIApplicationClass && [UIApplicationClass respondsToSelector:@selector(sharedApplication)]; if (hasApplication && [self shouldContinueWhenAppEntersBackground]) { __weak __typeof__ (self) wself = self; // 獲取單例 UIApplication * app = [UIApplicationClass performSelector:@selector(sharedApplication)]; // 獲取這個后臺線程的表示 UIBackgroundTaskIdentifier self.backgroundTaskId = [app beginBackgroundTaskWithExpirationHandler:^{ __strong __typeof (wself) sself = wself; // 后臺下載時間到了,就會調用這個 block,如果任務仍在下載就進行取消,調用 endBackgroundTask 方法通知系統該 backgroundTaskId 停止,并把 backgroundTaskId 狀態改為無效 if (sself) { [sself cancel]; [app endBackgroundTask:sself.backgroundTaskId]; sself.backgroundTaskId = UIBackgroundTaskInvalid; } }]; }#endif NSURLSession *session = self.unownedSession; if (!self.unownedSession) { // 會話配置 NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; sessionConfig.timeoutIntervalForRequest = 15; /** * 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. */ // 為此任務創建會話 // 我們發送 nil 作為代理隊列,所以創建 session 用于執行所有 delegate 調用和完成處理程序調用的串行操作隊列。 self.ownedSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; session = self.ownedSession; } self.dataTask = [session dataTaskWithRequest:self.request]; self.executing = YES; self.thread = [NSThread currentThread]; } // 開始 [self.dataTask resume]; if (self.dataTask) { if (self.progressBlock) { self.progressBlock(0, NSURLResponseUnknownLength); } dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStartNotification object:self]; }); } else { if (self.completedBlock) { self.completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Connection can't be initialized"}], YES); } }#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 Class UIApplicationClass = NSClassFromString(@"UIApplication"); if(!UIApplicationClass || ![UIApplicationClass respondsToSelector:@selector(sharedApplication)]) { return; } if (self.backgroundTaskId != UIBackgroundTaskInvalid) { UIApplication * app = [UIApplication performSelector:@selector(sharedApplication)]; [app endBackgroundTask:self.backgroundTaskId]; self.backgroundTaskId = UIBackgroundTaskInvalid; }#endif}

SDWebImage 源碼閱讀終于完事了,最后一章有些不細心,等有時間重新整理一下


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩爱爱视频| 久久精品这里热有精品| 一区二区三区精品99久久| 俺去了亚洲欧美日韩| 亚洲人成电影在线播放| 久久亚洲精品小早川怜子66| 国产一区二区三区免费视频| 国产亚洲欧洲高清一区| 91久久国产婷婷一区二区| 国产欧美亚洲视频| 26uuu另类亚洲欧美日本老年| 国产精品久久久久久亚洲调教| 亚洲国产美女久久久久| 国产精品v日韩精品| 亚洲国产另类 国产精品国产免费| 97在线看免费观看视频在线观看| 2019中文字幕在线观看| 91精品综合久久久久久五月天| 亚洲色图五月天| 成人在线激情视频| 久久91亚洲精品中文字幕| 日韩中文字幕亚洲| 中文字幕最新精品| 粗暴蹂躏中文一区二区三区| 精品久久久久久久久国产字幕| 欧美亚洲成人免费| 日韩免费在线观看视频| 91免费精品国偷自产在线| 成人黄色在线播放| 国产成人综合久久| 日韩高清人体午夜| 97香蕉超级碰碰久久免费软件| 国产精品亚洲综合天堂夜夜| 欧美黑人性视频| 国产噜噜噜噜噜久久久久久久久| 国产一区二区三区免费视频| 影音先锋日韩有码| 欧美日韩中文字幕日韩欧美| 欧美性xxxx| 成人黄色午夜影院| 日韩高清有码在线| 精品中文字幕在线2019| 日韩美女毛茸茸| 欧美高清视频一区二区| 在线视频免费一区二区| 欧美精品videosex牲欧美| 国产精品视频自拍| 久久久欧美精品| 国产精品999999| 欧美在线视频免费播放| 亚洲激情第一页| 精品无人区乱码1区2区3区在线| 日韩欧美中文字幕在线观看| 欧美国产日本在线| 91网在线免费观看| 久久人人爽国产| 欧美精品午夜视频| 秋霞成人午夜鲁丝一区二区三区| 国产成人高清激情视频在线观看| 欧美最猛性xxxxx亚洲精品| 色哟哟亚洲精品一区二区| 91日本在线视频| 欧美午夜激情小视频| 91高清免费在线观看| 国产成人亚洲综合91精品| 一级做a爰片久久毛片美女图片| 国产精品久久久久久久久久久不卡| 日韩电影大全免费观看2023年上| 欧美激情极品视频| 久久久久久久久久久久久久久久久久av| 久久久久久国产精品美女| 亚洲3p在线观看| 欧美日韩中文字幕| 久久精品中文字幕电影| 亚洲欧美国产va在线影院| 国产精品一区二区3区| 亚洲国产高潮在线观看| 久久精品夜夜夜夜夜久久| 国产精品日韩在线播放| 色噜噜亚洲精品中文字幕| 亚洲欧美日韩天堂| 欧美黄网免费在线观看| 欧美成人三级视频网站| 久久久女女女女999久久| 亚洲欧洲国产一区| 日韩69视频在线观看| 日韩成人免费视频| 美女999久久久精品视频| 久久免费高清视频| 亚洲精品美女在线观看播放| 中文字幕欧美亚洲| 欧美激情乱人伦一区| 欧美日韩午夜视频在线观看| 国产精品久久久久久久久久ktv| 国模极品一区二区三区| 成人97在线观看视频| 久久99亚洲精品| 精品国产美女在线| 精品久久久久久中文字幕一区奶水| 亚洲变态欧美另类捆绑| 国产精品日韩在线一区| 欧美一级片久久久久久久| 久久99久久99精品免观看粉嫩| 日韩在线激情视频| 午夜免费久久久久| 日韩免费av在线| 亚洲精品国产精品国自产观看浪潮| 亚洲成人av中文字幕| 日本精品视频在线观看| 国产精品久久av| 国产成人精品久久二区二区| 国产成人精品在线播放| 日产精品99久久久久久| 亚洲第一区在线观看| 欧美性猛交xxxx免费看| 综合网中文字幕| 精品国产欧美一区二区五十路| 欧美激情亚洲精品| 精品动漫一区二区| 国产精品福利在线观看| 8050国产精品久久久久久| 日韩av在线看| 日本sm极度另类视频| 国产精品成人va在线观看| 亚洲第一精品久久忘忧草社区| 亚洲精品久久在线| 亚洲电影中文字幕| 亚洲综合成人婷婷小说| 97国产在线观看| 久久久久久久影院| 啪一啪鲁一鲁2019在线视频| 国产极品jizzhd欧美| 欧美极品少妇xxxxx| 国产精品中文久久久久久久| 这里只有视频精品| 亚洲精品动漫100p| 成人激情黄色网| 亚洲福利小视频| 亚洲女性裸体视频| 亚洲国产精品va在线看黑人动漫| 国产精品欧美亚洲777777| 欧美大学生性色视频| 成人久久一区二区| 日韩精品中文字幕视频在线| 国产精品ⅴa在线观看h| 久久久精品2019中文字幕神马| 国产精品一区电影| 久久久免费观看| 在线观看欧美日韩| 亚洲视频777| 欧美性猛交丰臀xxxxx网站| 国内精品小视频在线观看| 精品久久久久久久中文字幕| 91性高湖久久久久久久久_久久99| 亚洲综合国产精品| 高清一区二区三区日本久| 8050国产精品久久久久久| 日本韩国欧美精品大片卡二| 日韩高清不卡av| 性亚洲最疯狂xxxx高清| 午夜精品国产精品大乳美女| 日韩av快播网址| 福利微拍一区二区| 亚洲精品98久久久久久中文字幕|