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

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

SDWebImage 源碼閱讀(四)

2019-11-09 13:56: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
欧美日韩国产页| 日韩av中文在线| 国产精品欧美日韩一区二区| 国产欧美一区二区三区久久人妖| 亚洲国内精品在线| 日韩在线高清视频| 久久久精品美女| 在线观看中文字幕亚洲| 久久久爽爽爽美女图片| 国产一区二区动漫| 国产亚洲一区精品| 欧美激情第99页| 一区二区三区四区在线观看视频| 91老司机精品视频| 夜夜躁日日躁狠狠久久88av| 粗暴蹂躏中文一区二区三区| 日韩精品极品在线观看播放免费视频| 欧美国产高跟鞋裸体秀xxxhd| 欧美一级淫片aaaaaaa视频| 欧美一级视频免费在线观看| 狠狠操狠狠色综合网| 精品久久久久久亚洲国产300| 日韩精品视频在线观看网址| 国产精品色视频| 欧美亚洲第一页| 成人深夜直播免费观看| 亚洲va男人天堂| 国模精品一区二区三区色天香| 国产精品色午夜在线观看| 成人写真视频福利网| 中文字幕亚洲一区在线观看| 欧美日韩国产黄| 国产精品jizz在线观看麻豆| 亚洲精品永久免费| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲视频电影图片偷拍一区| 欧美有码在线观看| 亚洲黄色在线观看| 97免费视频在线播放| 国产精品一二三视频| 日韩少妇与小伙激情| 久久国产精品久久久久久久久久| 欧美精品日韩www.p站| 亚洲欧美日本精品| 亚洲美女性生活视频| 国产精彩精品视频| 亚洲精品国产精品国自产观看浪潮| 国产精品∨欧美精品v日韩精品| 热99精品里视频精品| 北条麻妃99精品青青久久| 欧美精品videosex性欧美| 91久久国产精品91久久性色| 亚洲国产一区二区三区四区| 91理论片午午论夜理片久久| 日韩欧美亚洲国产一区| 97**国产露脸精品国产| 97超碰蝌蚪网人人做人人爽| 这里只有精品在线播放| 国产精品网站入口| 亚洲一区亚洲二区亚洲三区| 日韩高清欧美高清| 亚洲午夜激情免费视频| 欧美日韩视频在线| 亚洲一区亚洲二区| 91在线|亚洲| 欧美激情视频在线| 亚洲免费中文字幕| 91免费观看网站| 成人h视频在线观看播放| 亚洲精选在线观看| 在线播放日韩av| 亚洲国产成人精品电影| 激情成人在线视频| 亚洲精品国产免费| www欧美日韩| 中文字幕精品久久| 成人字幕网zmw| 久久精品中文字幕一区| 浅井舞香一区二区| 国产精品高潮呻吟久久av黑人| 国产男女猛烈无遮挡91| 在线播放日韩专区| 日韩欧美精品网址| 国产精品男人爽免费视频1| 欧美性理论片在线观看片免费| 欧洲s码亚洲m码精品一区| 亚洲最大福利视频网| 国产成人一区二| 精品国产乱码久久久久酒店| 日本久久久久久久久| 国产深夜精品福利| 亚洲第一综合天堂另类专| 久久久国产一区二区| 国产女精品视频网站免费| 国内外成人免费激情在线视频| 亚洲精品综合久久中文字幕| 国产99久久精品一区二区永久免费| 国产在线98福利播放视频| 亚洲午夜未满十八勿入免费观看全集| 91精品国产自产在线老师啪| 日韩va亚洲va欧洲va国产| 中文字幕亚洲一区二区三区五十路| 国产丝袜一区二区三区免费视频| 国产福利视频一区| 欧美色另类天堂2015| 91av国产在线| 亚洲xxxx妇黄裸体| 欧美日产国产成人免费图片| 亚洲欧美日韩一区二区在线| 亚洲第一男人天堂| 九九热这里只有在线精品视| 久久免费国产视频| 在线观看91久久久久久| 日韩中文在线观看| 欧美极品少妇xxxxⅹ裸体艺术| 欧美大码xxxx| 国自在线精品视频| 久久综合国产精品台湾中文娱乐网| 隔壁老王国产在线精品| 中文字幕国产亚洲2019| 国产在线观看精品| 国产热re99久久6国产精品| 亚洲网址你懂得| 狠狠久久五月精品中文字幕| 国产视频综合在线| 欧美成人sm免费视频| 色樱桃影院亚洲精品影院| 国产亚洲精品综合一区91| 久久久国产成人精品| 欧美日韩亚洲成人| 精品露脸国产偷人在视频| 亚洲天堂av女优| 欧美精品www| 久久中文字幕在线视频| 久久久久久噜噜噜久久久精品| 精品视频久久久久久| 亚洲自拍偷拍在线| 精品美女久久久久久免费| 久久精视频免费在线久久完整在线看| 亚洲国产精品va在线观看黑人| 中文字幕欧美国内| 亚洲一区二区三区久久| 91精品国产99| 国产亚洲xxx| 国内免费久久久久久久久久久| 性欧美xxxx视频在线观看| 国产成人精品久久二区二区| 欧美成人三级视频网站| 国产精品天天狠天天看| 国产视频精品久久久| 国产亚洲成精品久久| 久久精品国产精品亚洲| 亚洲欧美日本伦理| 亚洲九九九在线观看| 日韩中文字幕视频在线| 欧美日韩免费在线| 欧美国产日韩xxxxx| 国产成人一区二区在线| 亚洲免费电影在线观看| 欧美大片在线影院| 国产精品一区二区电影| 成人网在线观看| 在线成人激情黄色| 国产精品毛片a∨一区二区三区|国|