博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SDWebImage源码阅读(十一)SDWebImagePrefetcher
阅读量:5259 次
发布时间:2019-06-14

本文共 10203 字,大约阅读时间需要 34 分钟。

  SDWebImagePrefetcherDelegate

1 @protocol SDWebImagePrefetcherDelegate 
2 3 @optional 4 5 /** 6 * Called when an image was prefetched. 7 * 8 * @param imagePrefetcher The current image prefetcher 9 * @param imageURL The image url that was prefetched10 * @param finishedCount The total number of images that were prefetched (successful or not)11 * @param totalCount The total number of images that were to be prefetched12 */13 - (void)imagePrefetcher:(nonnull SDWebImagePrefetcher *)imagePrefetcher didPrefetchURL:(nullable NSURL *)imageURL finishedCount:(NSUInteger)finishedCount totalCount:(NSUInteger)totalCount;14 15 /**16 * Called when all images are prefetched.17 * @param imagePrefetcher The current image prefetcher18 * @param totalCount The total number of images that were prefetched (whether successful or not)19 * @param skippedCount The total number of images that were skipped20 */21 - (void)imagePrefetcher:(nonnull SDWebImagePrefetcher *)imagePrefetcher didFinishWithTotalCount:(NSUInteger)totalCount skippedCount:(NSUInteger)skippedCount;22 23 @end

  代理提供了两个方法:

  1.每次下载完成一个图片,finishedCount 表示对图像进行预取的总数(成功或失败)totalCount 图像将被预取的总数。

  2.当所有的图像下载完毕,totalCount 对图像进行预取的总数(无论成功或者失败) skippedCount 跳过的图像的总数,表示下载失败的的总数。

  命名block 

1 typedef void(^SDWebImagePrefetcherProgressBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls);2 typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls);

  SDWebImagePrefetcher 属性

1 /** 2  *  The web image manager 3  */ 4 @property (strong, nonatomic, readonly, nonnull) SDWebImageManager *manager; 5  6 /** 7  * Maximum number of URLs to prefetch at the same time. Defaults to 3. 8  */ 9 @property (nonatomic, assign) NSUInteger maxConcurrentDownloads;10 11 /**12  * SDWebImageOptions for prefetcher. Defaults to SDWebImageLowPriority.13  */14 @property (nonatomic, assign) SDWebImageOptions options;15 16 /**17  * Queue options for Prefetcher. Defaults to Main Queue.18  */19 @property (nonatomic, assign, nonnull) dispatch_queue_t prefetcherQueue;20 21 @property (weak, nonatomic, nullable) id 
delegate;

  SDWebImageManager *manager 网络图像管理器

  NSUInteger maxConcurrentDownloads 在同一时间预取的 URL 的最大数目,默认是 3 。

  SDWebImageOptions options 预取的选项,默认是 SDWebImageLowPriority。

  dispatch_queue_t prefetcherQueue 预取的队列,默认是主线程。

  id<SDWebImagePrefetcherDelegate> delegate 代理棒。

  SDWebImagePrefetcher 方法

1 /**2  * Return the global image prefetcher instance.3  */4 + (nonnull instancetype)sharedImagePrefetcher;

  返回一个全局的预取实例。单例对象。

1 /**2  * Allows you to instantiate a prefetcher with any arbitrary image manager.3  */4 - (nonnull instancetype)initWithImageManager:(nonnull SDWebImageManager *)manager NS_DESIGNATED_INITIALIZER;

  实例化一个预取图像管理对象。

1 /**2  * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching,3  * currently one image is downloaded at a time,4  * and skips images for failed downloads and proceed to the next image in the list5  *6  * @param urls list of URLs to prefetch7  */8 - (void)prefetchURLs:(nullable NSArray
*)urls;

  指定 URLs 列表给 SDWebImagePrefetcher 的预取队列。目前一次下载一个图像,跳过下载失败的图像,然后继续进入列表的下一次下载。

1 /** 2  * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching, 3  * currently one image is downloaded at a time, 4  * and skips images for failed downloads and proceed to the next image in the list 5  * 6  * @param urls            list of URLs to prefetch 7  * @param progressBlock   block to be called when progress updates;  8  *                        first parameter is the number of completed (successful or not) requests,  9  *                        second parameter is the total number of images originally requested to be prefetched10  * @param completionBlock block to be called when prefetching is completed11  *                        first param is the number of completed (successful or not) requests,12  *                        second parameter is the number of skipped requests13  */14 - (void)prefetchURLs:(nullable NSArray
*)urls15 progress:(nullable SDWebImagePrefetcherProgressBlock)progressBlock16 completed:(nullable SDWebImagePrefetcherCompletionBlock)completionBlock;

  指定 URLs 列表给 SDWebImagePrefetcher 的预取队列。目前一次下载一个图像,跳过下载失败的图像,然后继续进入列表的下一次下载。

  progressBlock 是下载进度更新时调用的 block。这个 block 的第一个参数是已经完成的或者不需要请求的数量。第二个参数是最开始需要预取的图像数量。

  completionBlock 是预取完成时调用的 block。这个 block 的第一个参数是已经完成的或者不需要请求的数量。第二个参数是跳过的请求的数量,请求失败的数量。

1 /**2  * Remove and cancel queued list3  */4 - (void)cancelPrefetching;

  移除并取消队列列表。

  SDWebImagePrefetcher.m

1 @interface SDWebImagePrefetcher () 2  3 @property (strong, nonatomic, nonnull) SDWebImageManager *manager; 4 @property (strong, nonatomic, nullable) NSArray
*prefetchURLs; 5 @property (assign, nonatomic) NSUInteger requestedCount; 6 @property (assign, nonatomic) NSUInteger skippedCount; 7 @property (assign, nonatomic) NSUInteger finishedCount; 8 @property (assign, nonatomic) NSTimeInterval startedTime; 9 @property (copy, nonatomic, nullable) SDWebImagePrefetcherCompletionBlock completionBlock;10 @property (copy, nonatomic, nullable) SDWebImagePrefetcherProgressBlock progressBlock;11 12 @end

  属性。

1 + (nonnull instancetype)sharedImagePrefetcher {2     static dispatch_once_t once;3     static id instance;4     dispatch_once(&once, ^{5         instance = [self new];6     });7     return instance;8 }

  单例方法实现。

1 - (nonnull instancetype)init { 2     return [self initWithImageManager:[SDWebImageManager new]]; 3 } 4  5 - (nonnull instancetype)initWithImageManager:(SDWebImageManager *)manager { 6     if ((self = [super init])) { 7         _manager = manager; 8         _options = SDWebImageLowPriority; 9         _prefetcherQueue = dispatch_get_main_queue();10         self.maxConcurrentDownloads = 3;11     }12     return self;13 }

  初始化方法。

1 - (void)setMaxConcurrentDownloads:(NSUInteger)maxConcurrentDownloads {2     self.manager.imageDownloader.maxConcurrentDownloads = maxConcurrentDownloads;3 }4 5 - (NSUInteger)maxConcurrentDownloads {6     return self.manager.imageDownloader.maxConcurrentDownloads;7 }

  maxConcurrentDownloads 的 setter 和 getter 方法。其实是给 self.manager.imageDownloader.maxConcurrentDownloads 赋值和取值。

1 - (void)prefetchURLs:(nullable NSArray
*)urls { 2 [self prefetchURLs:urls progress:nil completed:nil]; 3 } 4 5 - (void)prefetchURLs:(nullable NSArray
*)urls 6 progress:(nullable SDWebImagePrefetcherProgressBlock)progressBlock 7 completed:(nullable SDWebImagePrefetcherCompletionBlock)completionBlock { 8 [self cancelPrefetching]; // Prevent duplicate prefetch request 9 self.startedTime = CFAbsoluteTimeGetCurrent();10 self.prefetchURLs = urls;11 self.completionBlock = completionBlock;12 self.progressBlock = progressBlock;13 14 if (urls.count == 0) {15 if (completionBlock) {16 completionBlock(0,0);17 }18 } else {19 // Starts prefetching from the very first image on the list with the max allowed concurrency20 NSUInteger listCount = self.prefetchURLs.count;21 for (NSUInteger i = 0; i < self.maxConcurrentDownloads && self.requestedCount < listCount; i++) {22 [self startPrefetchingAtIndex:i];23 }24 }25 }

  指定 NSURL 的数组去下载。在开始前先调用了 cancelPrefetching 方法,防止重复预取下载。

1 - (void)cancelPrefetching {2     self.prefetchURLs = nil;3     self.skippedCount = 0;4     self.requestedCount = 0;5     self.finishedCount = 0;6     [self.manager cancelAll];7 }

  调用该方法后,所有的未完成的下载都会被清空,也就说现在 SDWebImagePrefetcher 只专注处理传进来的 NSURL 的数组,是无状态的下载,也就是要求传入的 NSURL 要完整。然后循环去调用下载方法。

1 - (void)startPrefetchingAtIndex:(NSUInteger)index { 2     if (index >= self.prefetchURLs.count) return; 3     self.requestedCount++; 4     [self.manager loadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 5         if (!finished) return; 6         self.finishedCount++; 7  8         if (image) { 9             if (self.progressBlock) {10                 self.progressBlock(self.finishedCount,(self.prefetchURLs).count);11             }12         }13         else {14             if (self.progressBlock) {15                 self.progressBlock(self.finishedCount,(self.prefetchURLs).count);16             }17             // Add last failed18             self.skippedCount++;19         }20         if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didPrefetchURL:finishedCount:totalCount:)]) {21             [self.delegate imagePrefetcher:self22                             didPrefetchURL:self.prefetchURLs[index]23                              finishedCount:self.finishedCount24                                 totalCount:self.prefetchURLs.count25              ];26         }27         if (self.prefetchURLs.count > self.requestedCount) {28             dispatch_async(self.prefetcherQueue, ^{29                 [self startPrefetchingAtIndex:self.requestedCount];30             });31         } else if (self.finishedCount == self.requestedCount) {32             [self reportStatus];33             if (self.completionBlock) {34                 self.completionBlock(self.finishedCount, self.skippedCount);35                 self.completionBlock = nil;36             }37             self.progressBlock = nil;38         }39     }];40 }

  该方法按 index 下标开始并行下载图片。 self.requestedCount、self.finishedCount、self.skippedCount 分别在对应的地方做 ++ 操作。执行一张图片下载完成后的代理方法,如果 self.requestedCount 小于 self.prefetchURLs.count 则异步在 self.prefetcherQueue 队列里面继续下载。

  当全部下载完毕后,执行全部下载完毕的代理方法,执行下载完成的 block。

1 - (void)reportStatus {2     NSUInteger total = (self.prefetchURLs).count;3     if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didFinishWithTotalCount:skippedCount:)]) {4         [self.delegate imagePrefetcher:self5                didFinishWithTotalCount:(total - self.skippedCount)6                           skippedCount:self.skippedCount7          ];8     }9 }

  执行全部下载完毕的代理方法。

参考链接:

END

 

转载于:https://www.cnblogs.com/chmhml/p/6973795.html

你可能感兴趣的文章
opencv删除轮廓
查看>>
实战分区表:SQL Server 2k5&2k8系列(三)
查看>>
JS简单的倒计时(代码优化)
查看>>
CSS2.0实现面包屑
查看>>
css font的简写规则
查看>>
CSS| 框模型-輪廓
查看>>
kafka报错 Replication factor: 3 larger than available brokers: 0.
查看>>
linux查看和修改PATH环境变量的方法
查看>>
浅谈自定义UITextField的方法
查看>>
h.264 Mode Decision
查看>>
《基于B/S中小型超市进销存管理系统的研究与设计》论文笔记(十六)
查看>>
主数据0
查看>>
HDU2001
查看>>
iOS-id类型
查看>>
ReactNative--View组件
查看>>
C#对.zip 存档读取和写入【转】
查看>>
zabbix图中出现中文乱码问题
查看>>
天眼系统的计划和日程管理
查看>>
linux c 获取系统时间
查看>>
day 09 课后作业
查看>>