SDWebImage源码阅读(四)

2020-06-29  本文已影响0人  落叶兮兮

上一篇中主要写了SDWebImageDownloader.h中一些属性和方法的作用,相应的链接为https://www.jianshu.com/p/1c67b94f1f9b
这一篇开始写SDWebImageDownloader.m中方法的具体实现.
在初始化的init方法中使用[NSURLSessionConfiguration defaultSessionConfiguration]初始化session配置,在里面可以看到有一部分代码,

//iPhone开发对应的userAgent
 userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
//watch 开发对应的userAgent
userAgent = [NSString stringWithFormat:@"%@/%@ (%@; watchOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[WKInterfaceDevice currentDevice] model], [[WKInterfaceDevice currentDevice] systemVersion], [[WKInterfaceDevice currentDevice] screenScale]];
//mac开发对应的userAgent
userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]];

后面根据配置创建会话的代码如下所示:

//delegateQueue参数:调度委托调用和完成处理程序的操作队列。该队列应该是串行队列,以确保回调的顺序正确。如果为nil,会话将创建一个串行操作队列来执行所有委托方法调用和完成处理程序调用。
self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
                                                 delegate:self
                                            delegateQueue:nil];
}

初始化配置完成后,根据.h文件中定义的方法,知道下载的方法是downloadImageWithURL,故接下来看这个方法内的实现。
方法中

//当operation为nil或者已经结束或者取消时,此时需要重新创建新的下载操作
if (!operation || operation.isFinished || operation.isCancelled) {
 operation = [self createDownloaderOperationWithUrl:url options:options];
}

在新的创建方法中使用到了cachePolicy,关于这个的枚举的定义如下:

1.[NSURLRequestUseProtocolCachePolicy]:默认策略,具体的缓存逻辑和协议的声明有关,如果协议没有声明,不需要每次重新验证cache。    如果请求协议头为no-cache,则表现为直接从后台请求数据
2.[NSURLRequestReloadIgnoringLocalCacheData]:忽略本地缓存,直接从后台请求数据
3.[NSURLRequestReloadIgnoringLocalAndRemoteCacheData]:忽略本地缓存数据、代理和其他中介的缓存,直接从后台请求数据
4.[NSURLRequestReturnCacheDataElseLoad]:优先从本地拿数据,且忽略请求生命时长和过期时间。但是如果没有本地cache,则请求源数据
5.[NSURLRequestReturnCacheDataDontLoad]:只从本地拿数据
6.[NSURLRequestReloadRevalidatingCacheData]:每次必须重新验证cache

之后创建新的NSURLRequest
相应的代码为:

  NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url
                                                                cachePolicy:cachePolicy
                                                            timeoutInterval:timeoutInterval];
    
    request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies);
    request.HTTPShouldUsePipelining = YES;
    if (self.headersFilter) {
        request.allHTTPHeaderFields = self.headersFilter(url, [self allHTTPHeaderFields]);
    }
    else {
        request.allHTTPHeaderFields = [self allHTTPHeaderFields];
    }
NSOperation<SDWebImageDownloaderOperationInterface> *operation = [[self.operationClass alloc] initWithRequest:request inSession:self.session options:options];
 if (self.urlCredential) {
        operation.credential = self.urlCredential;
    } else if (self.username && self.password) {
        operation.credential = [NSURLCredential credentialWithUser:self.username password:self.password persistence:NSURLCredentialPersistenceForSession];
    }

接下来就是下载顺序的处理,正常情况下是加入的队列,遵守的是先进先出的原则,对于后进先出的顺序,需要另外的处理。

//如果有传入优先级,则需要将传入的优先级赋值为操作
if (options & SDWebImageDownloaderHighPriority) {
        operation.queuePriority = NSOperationQueuePriorityHigh;
    } else if (options & SDWebImageDownloaderLowPriority) {
        operation.queuePriority = NSOperationQueuePriorityLow;
    }
    
//后进先出的处理,添加的新操作作为最后一个操作的依赖项来模拟后进先出的执行顺序。
    if (self.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
//最后的一个操作依赖于新的操作,即新的操作执行完才能执行最后的那个操作
        [self.lastAddedOperation addDependency:operation];
        self.lastAddedOperation = operation;
    }

之后添加相应的处理操作并且将队operation添加到operation queue中。
这部分的方法看完.

SDWebImage源码阅读(一)
SDWebImage源码阅读(二)
SDWebImage源码阅读(三)
SDWebImage源码阅读(四)
SDWebImage源码阅读(五)
SDWebImage源码阅读(六)

上一篇下一篇

猜你喜欢

热点阅读