1、SDWebImage源码解读之SDWebImageDownloaderSDWebImage源码解读之SDWebImageDownloaderSDWebImageDownloader这个类非常简单,作者的设计思路也很清晰,但是我想在这说点题外话。如果有人问你:你怎么看待编程这件事?你怎么回答。这个问题是我在看这个类的时候,忽然出现在我脑子中的。我突然意识到,其实不管是函数还是属性,他们都是数据。我们编写的所有程序都是在处理数据。函数本身也是一种特殊的数据。真正难的是生产数据的这一过程。举个例子,给你一堆菜籽,要求生产出油来。怎么办?我们首先为这个任务设计一个函数:- (油)用菜籽生产油(菜籽);
2、这就是我们最外层的函数,也应该是我们最开始想到的函数。然后经过我们的研究发现,这个生产过程很复杂,必须分工合作才能实现。于是我们把这个任务分割为好几个小任务:1. - (干净的菜籽)取出杂质(菜籽);2. - (炒熟的菜籽)把菜籽炒一下(干净的菜籽);3. - (蒸了的菜籽)把菜籽蒸一下(炒熟的菜籽);4. - (捆好的菜籽)把菜籽包捆成一块(蒸了的菜籽);5. - (油)撞击菜籽包(捆好的菜籽);大家有没有发现,整个榨油的过程就是对数据的处理。这一点其实很重要。如果没有把- (油)用菜籽生产油(菜籽);这一任务进行拆分,我们就会写出复杂无比的函数。那么就有人要问了,只要实现这个功能就行了呗。
3、其实这往往是写不出好代码的原因。整个任务的设计应该是事先就设计好的。任务被分割成更小更简单的部分,然后再去实现这些最小的任务,不应该是编写边分割任务,往往临时分割的任务(也算是私有函数吧)没有最正确的界限。有了上边合理的分工之后呢,我们就可以进行任务安排了。我们回到现实开发中来。上边5个子任务的难度是不同的。有的人可能基础比较差,那么让他去干筛菜籽这种体力活,应该没问题。那些炒或者蒸的子任务是要掌握火候的,也就是说有点技术含量。那么就交给能胜任这项工作的人去做。所有的这一切,我们只要事先定义好各自的生产结果就行了,完全不影响每个程序的执行。怎么样?大家体会到这种编程设计的好处了吗?我还可以进行
4、合并,把炒和煮合成一个小组,完全可行啊。好了这方面的思考就说这么多吧。如果我想买煮熟了的菜籽,是不是也很简单?有的人用原始的撞击菜籽包榨油,有的人却用最先进的仪器榨油,这就是编程技术和知识深度的区别啊。SDWebImageDownloaderOptions言归正传,当我们需要给某个功能添加Options的时候,一般使用枚举来实现。我们先看看支持的选项:typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) SDWebImageDownloaderLowPriority = 1 0, SDWebImageDownloaderProg
5、ressiveDownload = 1 1, / 带有进度 SDWebImageDownloaderUseNSURLCache = 1 2, / 使用URLCache SDWebImageDownloaderIgnoreCachedResponse = 1 3, / 不缓存响应 SDWebImageDownloaderContinueInBackground = 1 4, / 支持后台下载 SDWebImageDownloaderHandleCookies = 1 5, / 使用Cookies SDWebImageDownloaderAllowInvalidSSLCertificates =
6、1 6, / 允许验证SSL SDWebImageDownloaderHighPriority = 1 7, / 高权限 SDWebImageDownloaderScaleDownLargeImages = 1 8, / 裁剪大图片;这里提供了这么几种不同的选项,大家可以根据自己的需求选个合适的选项。这里作者使用了掩码。比如说,1 1 ,表示把1左移一位,我们把1携程二进制为:00000001,那么左移一位后就是:00000010 转成10进制后就是2,也就是说左移一位表示在原来的值上乘以2。再举个例子,当判断self.option是否是SDWebImageDownloaderIgnoreCa
7、chedResponse选项时,应该这么判断:self.option & SDWebImageDownloaderIgnoreCachedResponseSDWebImageDownloaderExecutionOrderSDWebImageDownloaderExecutionOrder定义了数据被调用的顺序。按照一般的想法。下载应该按照数据放入队列的顺序依次进行,但也支持后进先出这种方式。一个下载管理器应该这样管理下载,肯定有一个下载列表,我们可以假定这个列表保存在一个数组中,正常情况下我们应该每次取出数组中第1个元素来下载,这就是FIFO(先进先出)。那么我们要改为LIFO(后进先出),
8、应该是针对某一个下载的,不应该是把取出数据的顺序改为从数组的最后一个元素取出。typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) /* * Default value. All download operations will execute in queue style (first-in-first-out). */ SDWebImageDownloaderFIFOExecutionOrder, /* * All download operations will execute in stack style (las
9、t-in-first-out). */ SDWebImageDownloaderLIFOExecutionOrder;但是我有一个疑问,如果我只是想暂停某一个下载,我该怎么办呢?如果直接取消,那么点击继续的时候,要重新开启下载,肯定影响体验。这一点跟使用数组管理任务有点不同。辅助部分extern NSString * _Nonnull const SDWebImageDownloadStartNotification;extern NSString * _Nonnull const SDWebImageDownloadStopNotification;通过extern,我们就能够使用其他文件的
10、代码。typedef void(SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL);typedef void(SDWebImageDownloaderCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished);命名Blocktypedef NSDictionary S
11、DHTTPHeadersDictionary;typedef NSMutableDictionary SDHTTPHeadersMutableDictionary;命名字典typedef SDHTTPHeadersDictionary * _Nullable (SDWebImageDownloaderHeadersFilterBlock)(NSURL * _Nullable url, SDHTTPHeadersDictionary * _Nullable headers);这个block允许我们自定义请求头,通过Block传值,有一定的优点,我们可以拿到一些参数,然后在加工成我们需要的数据,最
12、后返回。SDWebImageDownloadTokenSDWebImageDownloadToken作为每一个下载的唯一身份标识,SDWebImageDownloader和我们平时开发中的下载还是又不一样的地方的,它弱化了下载过程,比较强调的是下载结果。不支持断点下载(当然这可能没有必要)。如果我们需要设计一个自己的下载管理者,我们就应该设计一个类似SDWebImageDownloadToken这样的下载对象封装类,我需要的所有信息,都能在这个对象中获取,大家如果有兴趣,可以看看MCDownloadManager./* * A token associated with each downlo
13、ad. Can be used to cancel a download */interface SDWebImageDownloadToken : NSObjectproperty (nonatomic, strong, nullable) NSURL *url;property (nonatomic, strong, nullable) id downloadOperationCancelToken;endSDWebImageDownloader.h/* * Decompressing images that are downloaded and cached can improve pe
14、rformance but can consume lot of memory. * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption. */property (assign, nonatomic) BOOL shouldDecompressImages;/* * The maximum number of concurrent downloads */property (assign, nonatomic) NSInteger maxConcu
15、rrentDownloads;/* * Shows the current amount of downloads that still need to be downloaded */property (readonly, nonatomic) NSUInteger currentDownloadCount;/* * The timeout value (in seconds) for the download operation. Default: 15.0. */property (assign, nonatomic) NSTimeInterval downloadTimeout;/*
16、* Changes download operations execution order. Default value is SDWebImageDownloaderFIFOExecutionOrder. */property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder;/* * Singleton method, returns the shared instance * * return global shared instance of downloader class */+ (nonnu
17、ll instancetype)sharedDownloader;/* * Set the default URL credential to be set for request operations. */property (strong, nonatomic, nullable) NSURLCredential *urlCredential;/* * Set username */property (strong, nonatomic, nullable) NSString *username;/* * Set password */property (strong, nonatomic
18、, nullable) NSString *password;/* * Set filter to pick headers for downloading image HTTP request. * * This block will be invoked for each downloading image request, returned * NSDictionary will be used as headers in corresponding HTTP request. */property (nonatomic, copy, nullable) SDWebImageDownlo
19、aderHeadersFilterBlock headersFilter;初始化方法/* * Creates an instance of a downloader with specified session configuration. * *Note*: timeoutIntervalForRequest is going to be overwritten. * return new instance of downloader class */- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSes
20、sionConfiguration *)sessionConfiguration NS_DESIGNATED_INITIALIZER;我们都知道: 一个NSURLSession会话,使用NSURLSessionConfiguration进行配置,利用这一点,我们在设计自己的网络框架的时候,可以参考NSURLSessionConfiguration。暴露少量的属性来配置网络请求,后期维护起来也比较容易。使用NS_DESIGNATED_INITIALIZER强调该方法是建议的初始化方法。其他的方法/* * Set a value for a HTTP header to be appended t
21、o each download HTTP request. * * param value The value for the header field. Use nil value to remove the header. * param field The name of the header field to set. */- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(nullable NSString *)field;/* * Returns the value of the specified HTT
22、P header field. * * return The value associated with the header field field, or nil if there is no corresponding header field. */- (nullable NSString *)valueForHTTPHeaderField:(nullable NSString *)field;/* * Sets a subclass of SDWebImageDownloaderOperation as the default * NSOperation to be used eac
23、h time SDWebImage constructs a request * operation to download an image. * * param operationClass The subclass of SDWebImageDownloaderOperation to set * as default. Passing nil will revert to SDWebImageDownloaderOperation. */- (void)setOperationClass:(nullable Class)operationClass;/* * Creates a SDW
24、ebImageDownloader async downloader instance with a given URL * * The delegate will be informed when the image is finish downloaded or an error has happen. * * see SDWebImageDownloaderDelegate * * param url The URL to the image to download * param options The options to be used for this download * pa
25、ram progressBlock A block called repeatedly while the image is downloading * note the progress block is executed on a background queue * param completedBlock A block called once the download is completed. * If the download succeeded, the image parameter is set, in case of error, * error parameter is
26、 set with the error. The last parameter is always YES * if SDWebImageDownloaderProgressiveDownload isnt use. With the * SDWebImageDownloaderProgressiveDownload option, this block is called * repeatedly with the partial image object and the finished argument set to NO * before to be called a last tim
27、e with the full image and finished argument * set to YES. In case of error, the finished argument is always YES. * * return A token (SDWebImageDownloadToken) that can be passed to -cancel: to cancel this operation */- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url opt
28、ions:(SDWebImageDownloaderOptions)options progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock;/* * Cancels a download that was previously queued using -downloadImageWithURL:options:progress:completed: * * param toke
29、n The token received from -downloadImageWithURL:options:progress:completed: that should be canceled. */- (void)cancel:(nullable SDWebImageDownloadToken *)token;/* * Sets the download queue suspension state */- (void)setSuspended:(BOOL)suspended;/* * Cancels all download operations in the queue */- (
30、void)cancelAllDownloads;SDWebImageDownloader.mproperty (strong, nonatomic, nonnull) NSOperationQueue *downloadQueue;property (weak, nonatomic, nullable) NSOperation *lastAddedOperation;property (assign, nonatomic, nullable) Class operationClass;property (strong, nonatomic, nonnull) NSMutableDictiona
31、ry *URLOperations;property (strong, nonatomic, nullable) SDHTTPHeadersMutableDictionary *HTTPHeaders;/ This queue is used to serialize the handling of the network responses of all the download operation in a single queueproperty (SDDispatchQueueSetterSementics, nonatomic, nullable) dispatch_queue_t barrierQueue;/ The session in which data tasks will runproperty (strong, nonatomic) NS
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1