Kingfisher源码解析系列,因为水平有限,哪里有错,肯请不吝赐教api
ImagePrefetcher是Kingfisher提供预加载功能的一个类,提供了一下功能数组
先来看下stop函数的实现,实现比较简单,在预加载的队列里异步的执行把标志位stopped设置为true,而且取消当前全部未完成的下载任务,看起来很简单。缓存
public func stop() {
pretchQueue.async {
if self.finished { return }
self.stopped = true
self.tasks.values.forEach { $0.cancel() }
}
}
复制代码
可是stopped这个标志位只在网络请求结束的回调里去判断了,这就会发生一些歧义,交给读者去判断Kingfisher这么作是不是合理的?当调用stop函数时,会出现如下几种状况以及对应的结果bash
对于状况1和状况2都是合理的,而且是绝大部分都会是状况1和状况2,对于状况3,调用stop时并无真正的去中止,可是这种状况也是较少出现的。网络
对于stop方法,喵神的注释是这样的并发
/// Stops current downloading progress, and cancel any future prefetching activity that might be occuring.异步
我第一次看代码,就想为何要有2个呢?为何这么设计呢?这里以缓存进度的回调举例,它们两个的缘由是同样的。先来看下定义,async
public typealias PrefetcherProgressBlock =
((_ skippedResources: [Resource], _ failedResources: [Resource], _ completedResources: [Resource]) -> Void)
public typealias PrefetcherSourceProgressBlock =
((_ skippedSources: [Source], _ failedSources: [Source], _ completedSources: [Source]) -> Void)
复制代码
咱们发现基本是同样的,只是回调里的参数类型不同,一个Resource,另外一个Source。若是你对这2个类型比较了解,想必你应该能猜到这么设计的缘由了。ide
Source是一个枚举,Kingfisher中为UIImage提供数据源用的,定义以下,有2个case,一个是关联了Resource,另外一个关联了ImageDataProvider函数
public enum Source {
case network(Resource)
case provider(ImageDataProvider)
}
复制代码
Resource是一个协议,定义以下,提供数据源的真正类型之一,通常用于加载网络图片
public protocol Resource {
var cacheKey: String { get }
var downloadURL: URL { get }
}
复制代码
ImageDataProvider也是一个协议,定义以下,提供数据源的另外一个真正类型,通常用于本地图片
public protocol ImageDataProvider {
var cacheKey: String { get }
func data(handler: @escaping (Result<Data, Error>) -> Void)
}
复制代码
回答上面的问题,因为咱们通常状况下预加载的都是网络图片,所以提供一个方便咱们使用的回调,但为了覆盖到全部状况,就提供了2个状况的回调,这个在ImagePrefetcher的便利初始化方法里咱们就能看出来,当使用[URL](注:在URL的扩展里实现了Resource协议)或者[Resource]初始化的时候,就使用PrefetcherProgressBlock,当使用[Source]初始化时,就使用的PrefetcherSourceProgressBlock