iOS 面試題:SDWebImgae底層原理分析

SDWebImage

是用于加載服務(wù)器圖片庫浙于,對UIkit做了二次封裝

一港令、SDWebImage的加載流程

SDWebImage加載流程.png
  • setImageWithURL:placeholderImage:options: 會先把placeholderImage 顯示.
  • SDWebImageManager根據(jù) URL 通過集畅。SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交給 SDImageCache 從內(nèi)存內(nèi)存緩存查找是否有圖片讥珍,如果內(nèi)存中已經(jīng)有圖片緩存徙融,SDImageCacheDelegate 回調(diào) imageCache:didFindImage:forKey:userInfo:SDWebImageManager
  • 如果內(nèi)存緩存中沒有哭靖,生成 NSInvocationOperation添加到隊列開始從硬盤緩存查找圖片是否已經(jīng)緩存具垫。根據(jù) URLKey 在硬盤緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進行的操作试幽,所以回主線程進行結(jié)果回調(diào) notifyDelegate:筝蚕。
  • 如果從硬盤緩存中查到了圖片,則將圖片添加到內(nèi)存緩存中(如果空閑內(nèi)存過小铺坞,會先清空內(nèi)存緩存)起宽,進而回調(diào)展示圖片。
  • 如果從緩存中找不到圖片济榨,執(zhí)行回調(diào)方法 imageCache:didNotFindImageForKey:userInfo:燎含。
  • 共享或重新生成一個下載器 SDWebImageDownloader開始下載圖片。數(shù)據(jù)下載完成后交給 SDWebImageDecoder 做圖片解碼處理腿短。
  • 圖片解碼處理在一個 NSOperationQueue 完成屏箍,不會拖慢主線程 UI。如果有需要對下載的圖片進行二次處理橘忱,最好也在這里完成赴魁,效率會好很多。
  • 在主線程 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成钝诚,imageDecoder:didFinishDecodingImage:userInfo:回調(diào)給 SDWebImageDownloader颖御。imageDownloader:didFinishWithImage: 回調(diào)給 SDWebImageManager 告知圖片下載完成。
  • 通知所有的downloadDelegates下載完成,回調(diào)給需要的地方展示圖片潘拱。將圖片保存到 SDImageCache 中疹鳄,內(nèi)存緩存和硬盤緩存同時保存。寫文件到硬盤也在以單獨 NSInvocationOperation完成芦岂,避免拖慢主線程瘪弓。
  • SDImageCache 在初始化的時候會注冊一些消息通知,在內(nèi)存警告或退到后臺的時候清理內(nèi)存圖片緩存禽最,應(yīng)用結(jié)束的時候清理過期圖片腺怯。

一、SDWebImage的圖片緩存

圖片下載完成后川无,SDWebImage提供了對圖片進行了緩存呛占,主要由SDImageCache完成。該類負責(zé)處理內(nèi)存緩存以及一個可選的磁盤緩存懦趋,其中磁盤緩存的寫操作是異步的晾虑,不會對UI造成影響。
SDImageCache是繼承自NSCache仅叫,之所以繼承走贪,是因為NSCache是系統(tǒng)管理的,開發(fā)者不能去管理緩存

圖片緩存分為內(nèi)存緩存和磁盤緩存

1.內(nèi)存緩存的處理由NSCache對象實現(xiàn)惑芭,NSCache類似一個集合的容器坠狡,它存儲key-value對,類似于nsdictionary類遂跟,我們通常使用緩存來臨時存儲短時間使用但創(chuàng)建昂貴的對象逃沿,重用這些對象可以優(yōu)化新能,同時這些對象對于程序來說不是緊要的幻锁,如果內(nèi)存緊張就會自動釋放凯亮。

2.磁盤緩存的處理使用NSFileManager對象實現(xiàn),圖片存儲的位置位于cache文件夾哄尔,另外SDImageCache還定義了一個串行隊列來異步存儲圖片假消。

3.SDImageCache提供了大量方法來緩存、獲取岭接、移除及清空圖片富拗。對于圖片的索引,我們通過一個key來索引鸣戴,在內(nèi)存中啃沪,我們將其作為NSCache的key值,而在磁盤中窄锅,我們用這個key值作為圖片的文件名创千,對于一個遠程下載的圖片其url實作為這個key的最佳選擇。

2、存儲圖片

先在內(nèi)存中放置一份緩存追驴,如果需要緩存到磁盤械哟,將磁盤緩存操作作為一個task放到串行隊列中處理,會先檢查圖片格式是jpeg還是png殿雪,將其轉(zhuǎn)換為響應(yīng)的圖片數(shù)據(jù)宿饱,最后吧數(shù)據(jù)寫入磁盤中(文件名是對key值做MD5后的串)爹橱。

3染苛、查詢圖片

內(nèi)存和磁盤查詢圖片API:

 - (UIImage *)imageFromMemoryCacheForKey:(NSString *)key;
 - (UIImage *)imageFromDiskCacheForKey:(NSString *)key;

查看本地是否存在key指定的圖片拓哟,使用一下API:

  • (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock;
    4几缭、移除圖片

移除圖片API:

- (void)removeImageForKey:(NSString *)key;
- (void)removeImageForKey:(NSString *)key withCompletion:(SDWebImageNoParamsBlock)completion;
- (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk;
- (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(SDWebImageNoParamsBlock)completion;

5河泳、清理圖片(磁盤)

清空磁盤圖片可以選擇完全清空和部分清空,完全清空就是吧緩存文件夾刪除年栓。

  • (void)clearDisk;
  • (void)clearDiskOnCompletion:(SDWebImageNoParamsBlock)completion;
    部分清理 會根據(jù)設(shè)置的一些參數(shù)移除部分文件拆挥,主要有兩個指標(biāo):文件的緩存有效期(maxCacheAge:默認是1周)和最大緩存空間大小(maxCacheSize:如果所有文件大小大于最大值某抓,會按照文件最后修改時間的逆序纸兔,以每次一半的遞歸來移除哪些過早的文件,知道緩存文件總大小小于最大值)否副,具體代碼參考- (void)cleanDiskWithCompletionBlock汉矿;

6、小結(jié)

SDImageCache處理提供以上API备禀,還提供了獲取緩存大小洲拇,緩存中圖片數(shù)量等API,
常用的接口和屬性:

  (1)-getSize  :獲得硬盤緩存的大小

  (2)-getDiskCount : 獲得硬盤緩存的圖片數(shù)量

  (3)-clearMemory  : 清理所有內(nèi)存圖片

  (4)- removeImageForKey:(NSString *)key  系列的方法 : 從內(nèi)存曲尸、硬盤按要求指定清除圖片

  (5)maxMemoryCost  :  保存在存儲器中像素的總和

  (6)maxCacheSize  :  最大緩存大小 以字節(jié)為單位赋续。默認沒有設(shè)置,也就是為0另患,而清理磁盤緩存的先決條件為self.maxCacheSize > 0纽乱,所以0表示無限制。

  (7)maxCacheAge : 在內(nèi)存緩存保留的最長時間以秒為單位計算昆箕,默認是一周

一鸦列、SDWebImage的圖片下載

  • SDWebImageDownloader圖片下載器,負責(zé)圖片異步下載鹏倘,并對圖片加載做了優(yōu)化處理
  • 圖片的下載操作放在一個NSOperationQueue并發(fā)操作隊列中敛熬,隊列默認最大并發(fā)數(shù)是6
  • 每個圖片對應(yīng)一些回調(diào)(下載進度,完成回調(diào)等)第股,回調(diào)信息會存在downloader的URLCallbacks(一個字典应民,key是url地址,value是圖片下載回調(diào)數(shù)組)中,URLCallbacks可能被多個線程訪問诲锹,所以downloader把下載任務(wù)放在一個barrierQueue中繁仁,并設(shè)置屏障保證同一時間只有一個線程訪問URLCallbacks。在創(chuàng)建回調(diào)URLCallbacks的block中創(chuàng)建了一個NSOperation并添加到NSOperationQueue中归园。
  • 每個圖片下載都是一個operation類黄虱,創(chuàng)建后添加到一個隊列中,SDWebimage定義了一個協(xié)議 SDWebImageOperation作為圖片下載操作的基礎(chǔ)協(xié)議庸诱,聲明了一個cancel方法捻浦,用于取消操作。
 @protocol SDWebImageOperation <NSObject>
-(void)cancel;
 @end
  • 對于圖片的下載桥爽,SDWebImageDownloaderOperation完全依賴于NSURLConnection類朱灿,繼承和實現(xiàn)了NSURLConnectionDataDelegate協(xié)議的方法
connection:didReceiveResponse:
connection:didReceiveData:
connectionDidFinishLoading:
connection:didFailWithError:
connection:willCacheResponse:
connectionShouldUseCredentialStorage:
-connection:willSendRequestForAuthenticationChalleng
-connection:didReceiveData:方法,接受數(shù)據(jù)钠四,創(chuàng)建一個CGImageSourceRef對象盗扒,在首次獲取數(shù)據(jù)時(圖片width,height)缀去,圖片下載完成之前侣灶,使用CGImageSourceRef對象創(chuàng)建一個圖片對象,經(jīng)過縮放缕碎、解壓操作生成一個UIImage對象供回調(diào)使用褥影,同時還有下載進度處理。
注:縮放:SDWebImageCompat中SDScaledImageForKey函數(shù)
 解壓:SDWebImageDecoder文件中decodedImageWithImage

SDWebImageDownloaderOption
1.繼承自NSOperation類咏雌,沒有簡單實現(xiàn)main方法凡怎,而是采用更加靈活的start方法,以便自己管理下載的狀態(tài)
2.start方法中創(chuàng)建了下載使用的NSURLConnections對象处嫌,開啟了圖片的下載栅贴,并拋出一個下載開始的通知,
3.小結(jié):下載的核心是利用NSURLSession加載數(shù)據(jù)熏迹,每個圖片的下載都有一個operation操作來完成檐薯,并將這些操作放到一個操作隊列中,這樣可以實現(xiàn)圖片的并發(fā)下載注暗。

SDWebImageDecoder(異步對圖片進行解碼)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坛缕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子捆昏,更是在濱河造成了極大的恐慌赚楚,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骗卜,死亡現(xiàn)場離奇詭異宠页,居然都是意外死亡左胞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門举户,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烤宙,“玉大人,你說我怎么就攤上這事俭嘁√烧恚” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵供填,是天一觀的道長拐云。 經(jīng)常有香客問我,道長近她,這世上最難降的妖魔是什么叉瘩? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮泄私,結(jié)果婚禮上房揭,老公的妹妹穿的比我還像新娘备闲。我一直安慰自己晌端,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布恬砂。 她就那樣靜靜地躺著咧纠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪泻骤。 梳的紋絲不亂的頭發(fā)上漆羔,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音狱掂,去河邊找鬼演痒。 笑死,一個胖子當(dāng)著我的面吹牛趋惨,可吹牛的內(nèi)容都是我干的鸟顺。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼器虾,長吁一口氣:“原來是場噩夢啊……” “哼讯嫂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起兆沙,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤欧芽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后葛圃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體千扔,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡憎妙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了曲楚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尚氛。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖洞渤,靈堂內(nèi)的尸體忽然破棺而出阅嘶,到底是詐尸還是另有隱情,我是刑警寧澤载迄,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布讯柔,位于F島的核電站,受9級特大地震影響护昧,放射性物質(zhì)發(fā)生泄漏魂迄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一惋耙、第九天 我趴在偏房一處隱蔽的房頂上張望捣炬。 院中可真熱鬧,春花似錦绽榛、人聲如沸湿酸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽推溃。三九已至,卻和暖如春届腐,著一層夾襖步出監(jiān)牢的瞬間铁坎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工犁苏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留硬萍,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓围详,卻偏偏與公主長得像朴乖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子短曾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

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