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