这一篇我们来解决最后的问题,使用 SDWebImage 中下载图片的类 SDWebImageDownloader,这个类学习完以后,我们对 SDWebImage 的理解会更加深刻。
在上面我们看到的下载图片方法,并没有涉及到核心代码,原来是通过以下初始化来进入 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 源码阅读终于完事了,最后一章有些不细心,等有时间重新整理一下
新闻热点
疑难解答