Kingfisher源碼解析系列,因爲水平有限,哪裏有錯,肯請不吝賜教git
本篇文章主要介紹Processor和CacheSerializer的基本定義和調用時機,以及利用兩者擴展Kingfisher以支持webp格式的圖片github
Kingfisher中Processor是一個協議,定義了對原始數據進行加工處理轉換成UIImage的能力(Kingfisher緩存的是處理成功以後的UIImage,根據options的值來決定是否緩存原始數據)。 這裏的原始數據是指ImageProcessItem,它是一個枚舉類型。Processor和ImageProcessItem定義以下,都是特別簡單web
public enum ImageProcessItem {
case image(KFCrossPlatformImage)
case data(Data)
}
public protocol ImageProcessor {
//標識符,在緩存的時候用到,用於區分原始數據和處理加工以後的數據的
var identifier: String { get }
//交給具體的實現類去實現,ImageProcessItem,最終返回一個UIImage
func process(item: ImageProcessItem, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage?
}
複製代碼
若是你瞭解過Kingfisher,請嘗試回答下這2個問題緩存
ImageProcessor.process在何時調用,在調用的時候會傳遞什麼類型的數據?bash
Kingfisher中CacheSerializer定義了圖片序列化和反序列化的能力,也是一個協議網絡
public protocol CacheSerializer {
func data(with image: KFCrossPlatformImage, original: Data?) -> Data?
func image(with data: Data, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage?
}
複製代碼
func data(with image: KFCrossPlatformImage, original: Data?) -> Data?
把image序列化成data,以便寫入文件func image(with data: Data, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage?
把data反序列化爲UIImageKingfisher自己是不支持webp格式的圖片,可是能夠利用Processor和CacheSerializer對Kingfisher進行擴展,讓Kingfisher支持webP格式的圖片ide
WebP 標準是 Google 定製的,迄今爲止也只有 Google 發佈的 libwebp 實現了該的編解碼 。 因此這個庫也是該格式的事實標準。post
所以要想支持webp格式的圖片,須要依賴libwebp庫,用來實現圖片的編碼和解碼,對於這塊的代碼我是從SDWebImageWebPCoder複製過來的,而且去掉了對動圖的支持和一些SD配置的代碼,若是你對這塊感興趣,請參考源碼,因爲SD是OC寫的,因此這部分我用的也是OC,最終給UIImage添加了一個分類,提供了下面2個方法fetch
@interface UIImage (WebP)
//序列化爲Data
@property(nonatomic,strong,readonly,nullable) NSData *webPData;
//經過data反序列化爲UIImage
+ (nullable instancetype)imageWithWebPData:(NSData *)webPdata;
+
@end
複製代碼
在process判斷item的類型,如果image則直接返回,如果data則反序列化爲UIImageui
public struct WebPProcessor: ImageProcessor {
public static let `default` = WebPProcessor()
public let identifier = "WebPProcessor"
public init() {}
public func process(item: ImageProcessItem, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage? {
switch item {
case .image(let image):
return image
case .data(let data):
return UIImage(webPData: data)
}
}
}
複製代碼
public struct WebPCacheSerializer: CacheSerializer {
public static let `default` = WebPCacheSerializer()
private init() {}
public func data(with image: KFCrossPlatformImage, original: Data?) -> Data? {
return image.webPData;
}
public func image(with data: Data, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage? {
return UIImage(webPData: data);
}
}
複製代碼
if let url = URL(string:"http://q21556z4z.bkt.clouddn.com/123.webp?e=1575537931&token=7n8bncOpnUSrN4mijeEAJRdVXnC-jm-mk5qTjKjR:L1_MWy3xugv9ct6PD294CHzwiSE=&attname=") {
imageView.kf.setImage(
with: url,
options: [.processor(WebPProcessor.default), .cacheSerializer(WebPCacheSerializer.default)]
)
}
複製代碼
雖然說上面的代碼都比較簡單,可是我感受Kingfisher的這個設計真的挺好的,可擴展支持任意類型的圖片,而且Processor是用來加工處理圖片的,能作的還有其餘方面,好比Kingfisher中提供了多種實現類,好比圓角的RoundCornerImageProcessor,顯示高清圖的DownsamplingImageProcessor,組裝多種Processor的GeneralProcessor。 demo地址