Kingfisher源碼解析之Processor和CacheSerializer

Kingfisher源碼解析系列赦役,由于水平有限嚷量,哪里有錯(cuò)镇饮,肯請(qǐng)不吝賜教

Processor

Processor介紹

Kingfisher中Processor是一個(gè)協(xié)議耗绿,定義了對(duì)原始數(shù)據(jù)進(jìn)行加工處理轉(zhuǎn)換成UIImage的能力(Kingfisher緩存的是處理成功之后的UIImage,根據(jù)options的值來決定是否緩存原始數(shù)據(jù))砾隅。
這里的原始數(shù)據(jù)是指ImageProcessItem误阻,它是一個(gè)枚舉類型。Processor和ImageProcessItem定義如下晴埂,都是特別簡單

public enum ImageProcessItem {
    case image(KFCrossPlatformImage)
    case data(Data)
}
public protocol ImageProcessor {
    //標(biāo)識(shí)符究反,在緩存的時(shí)候用到,用于區(qū)分原始數(shù)據(jù)和處理加工之后的數(shù)據(jù)的
    var identifier: String { get }
    //交給具體的實(shí)現(xiàn)類去實(shí)現(xiàn)儒洛,ImageProcessItem精耐,最終返回一個(gè)UIImage
    func process(item: ImageProcessItem, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage?
}
關(guān)于Processor的兩個(gè)問題

如果你了解過Kingfisher,請(qǐng)嘗試回答下這2個(gè)問題

  1. ImageProcessor.process都在什么時(shí)候調(diào)用呢琅锻?
  2. ImageProcessItem關(guān)聯(lián)了2種類型卦停,一種是Data,另一種是UIImage浅浮,那么這2種類型分別什么時(shí)候會(huì)用到呢?

ImageProcessor.process在什么時(shí)候調(diào)用捷枯,在調(diào)用的時(shí)候會(huì)傳遞什么類型的數(shù)據(jù)滚秩?

  1. 當(dāng)從網(wǎng)絡(luò)上下載圖片成功之后,會(huì)調(diào)用process把下載成功的data加工處理成我們需要的UIImage淮捆。很明顯這種情況下傳遞的是Data類型郁油。
  2. 當(dāng)source是ImageDataProvider時(shí),從source中獲取到Data之后攀痊,會(huì)調(diào)用process把data加工處理成我們需要的UIImage桐腌。很明顯這種情況下傳遞的也是Data類型。
  3. 當(dāng)讀取緩存失敗苟径,但讀取原始數(shù)據(jù)緩存成功之后案站,會(huì)調(diào)用process把原始數(shù)據(jù)加工處理成我們需要的UIImage。這種情況會(huì)先把讀取到的data使用cacheSerializer反序列化為UIImage棘街,然后傳遞UIImage類型

CacheSerializer

CacheSerializer介紹

Kingfisher中CacheSerializer定義了圖片序列化和反序列化的能力蟆盐,也是一個(gè)協(xié)議

public protocol CacheSerializer {
    func data(with image: KFCrossPlatformImage, original: Data?) -> Data?
    func image(with data: Data, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage?
}
CacheSerializer的調(diào)用時(shí)機(jī)
  1. 當(dāng)需要磁盤緩存時(shí),會(huì)調(diào)用func data(with image: KFCrossPlatformImage, original: Data?) -> Data?把image序列化成data遭殉,以便寫入文件
  2. 當(dāng)從磁盤讀取數(shù)據(jù)時(shí)石挂,會(huì)調(diào)用func image(with data: Data, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage?把data反序列化為UIImage

使用Processor和CacheSerializer擴(kuò)展Kingfisher,使Kingfisher支持webP格式的圖片

Kingfisher本身是不支持webp格式的圖片险污,但是可以利用Processor和CacheSerializer對(duì)Kingfisher進(jìn)行擴(kuò)展痹愚,讓Kingfisher支持webP格式的圖片

WebP 標(biāo)準(zhǔn)是 Google 定制的,迄今為止也只有 Google 發(fā)布的 libwebp 實(shí)現(xiàn)了該的編解碼 。 所以這個(gè)庫也是該格式的事實(shí)標(biāo)準(zhǔn)拯腮。

因此要想支持webp格式的圖片窖式,需要依賴libwebp庫,用來實(shí)現(xiàn)圖片的編碼和解碼疾瓮,對(duì)于這塊的代碼我是從SDWebImageWebPCoder復(fù)制過來的脖镀,并且去掉了對(duì)動(dòng)圖的支持和一些SD配置的代碼,如果你對(duì)這塊感興趣狼电,請(qǐng)參考源碼蜒灰,由于SD是OC寫的,所以這部分我用的也是OC肩碟,最終給UIImage添加了一個(gè)分類强窖,提供了下面2個(gè)方法

@interface UIImage (WebP)
//序列化為Data
@property(nonatomic,strong,readonly,nullable) NSData *webPData;
//通過data反序列化為UIImage
+ (nullable instancetype)imageWithWebPData:(NSData *)webPdata;
+ 
@end
實(shí)現(xiàn)Processor

在process判斷item的類型,若是image則直接返回削祈,若是data則反序列化為UIImage

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)
        }
    }
}
CacheSerializer
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)]
    )
}

補(bǔ)充

雖說上面的代碼都比較簡單翅溺,但是我感覺Kingfisher的這個(gè)設(shè)計(jì)真的挺好的,可擴(kuò)展支持任意類型的圖片髓抑,并且Processor是用來加工處理圖片的咙崎,能做的還有其他方面,比如Kingfisher中提供了多種實(shí)現(xiàn)類吨拍,比如圓角的RoundCornerImageProcessor褪猛,顯示高清圖的DownsamplingImageProcessor,組裝多種Processor的GeneralProcessor羹饰。
demo地址

參考

SDWebImageWebPCoder
移動(dòng)端圖片格式調(diào)研
libwebp

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末夺姑,一起剝皮案震驚了整個(gè)濱河市憎乙,隨后出現(xiàn)的幾起案子泥兰,更是在濱河造成了極大的恐慌文留,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馍资,死亡現(xiàn)場(chǎng)離奇詭異筒主,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鸟蟹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門物舒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人戏锹,你說我怎么就攤上這事冠胯。” “怎么了锦针?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵荠察,是天一觀的道長置蜀。 經(jīng)常有香客問我,道長悉盆,這世上最難降的妖魔是什么盯荤? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮焕盟,結(jié)果婚禮上秋秤,老公的妹妹穿的比我還像新娘。我一直安慰自己脚翘,他們只是感情好灼卢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著来农,像睡著了一般鞋真。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沃于,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天涩咖,我揣著相機(jī)與錄音,去河邊找鬼繁莹。 笑死檩互,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咨演。 我是一名探鬼主播闸昨,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼雪标!你這毒婦竟也來了零院?” 一聲冷哼從身側(cè)響起溉跃,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤村刨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后撰茎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嵌牺,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年龄糊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逆粹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡炫惩,死狀恐怖僻弹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情他嚷,我是刑警寧澤蹋绽,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布芭毙,位于F島的核電站,受9級(jí)特大地震影響卸耘,放射性物質(zhì)發(fā)生泄漏退敦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一蚣抗、第九天 我趴在偏房一處隱蔽的房頂上張望侈百。 院中可真熱鬧,春花似錦翰铡、人聲如沸钝域。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽网梢。三九已至,卻和暖如春赂毯,著一層夾襖步出監(jiān)牢的瞬間战虏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工党涕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留烦感,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓膛堤,卻偏偏與公主長得像手趣,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肥荔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容