SDWebImage的原理以及使用流程
這個類庫是一個支持加載來自網(wǎng)絡(luò)的遠(yuǎn)程圖片脐彩,并且具有緩存管理`異步下載`同一個URL下載次數(shù)控制和優(yōu)化等特征。
SDWebImage支持異步圖片下載和緩存梅誓,提供了UIImageView+WebCacha的分類,方便實(shí)用梗掰。
加載圖片等流程大致如下:
1:
setImageWithURL:placeholderImage:options:會先把placeholderImage顯示及穗,然后SDWebImageManager根據(jù)URL開始處理圖片。
2:
進(jìn)入SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交給SDImageCache從緩存查找圖片是否已經(jīng)下載埂陆。
3:
先從內(nèi)存圖片緩存查找是否有圖片,如果內(nèi)存中已經(jīng)有圖片緩存购裙, SDImageCacheDelegate回調(diào)imageCache:didFindImage:forKey:userInfo:到SDWebImageManager著摔。
4:
SDWebImageManagerDelegate回調(diào)webImageManager:didFinishWithIamge:到UIImageView+WebCache等前端展示圖片。
5:
如果內(nèi)存緩存中沒有禾锤,生成NSInvocatioinOperation添加到隊列開始從硬盤查找圖片是否已經(jīng)緩存摹察。
6:
根據(jù)URLKey在硬盤緩存目錄下嘗試讀取圖片文件。這一步時在NSOperation進(jìn)行的操作黄娘,所以回主線程進(jìn)行結(jié)果回調(diào)notifyDelegate克滴。
7:
如果上一操作從硬盤讀取到了圖片,將圖片添加到內(nèi)存緩存中(如果空閑內(nèi)存過小劝赔,會先清空內(nèi)存緩存。SDImageCacheDelegate回調(diào)imageCache:didFindImage:forKey:userInfo:杂伟。進(jìn)而回調(diào)展示圖片仍翰。
如果從硬盤緩存目錄讀取不到圖片,說明所有緩存都不存在該圖片越平,需要下載圖片,回調(diào)imageCache:didNotFindImageForKey:userInfo:喧笔。
9:
共享或重新生成一個下載器SDWebImageDownloader開始下載圖片书闸。
10:
圖片下載由NSURLConnection來做利凑,實(shí)現(xiàn)相關(guān)delegate來判斷圖片下載中`下載完成和下載失敗。
11:
connection:didReceiveData:中利用ImageIO做了按照圖片下載進(jìn)圖加載效果哀澈。
12:
connectionDidFinishLoading:數(shù)據(jù)下載完成后交給SDWebImageDecoder做圖片解碼處理割按。
13:
圖片解碼處理在一個NSOperationQueue完成,不會拖慢主線程UI适荣。如果有需要對下載的圖片進(jìn)行二次處理,最好也在這里完成够吩,效率會好很多丈氓。
14:
在主線程notifyDelegateOnMainThreadWithInfo:宣告解碼完成,imageDecoder:didFinishDecodingIamge:userInfo:回調(diào)給SDWebImageDownloader 湾笛。
15:
imageDownloader:didFinishWithImage:回調(diào)給SDWebImageManager告知圖片下載完成闰歪。
16:
通知所有的downloadDelegates下載完成,回調(diào)給需要的地方展示圖片课竣。
17:
將圖片保存到SDImageCache中于樟,內(nèi)存緩存和硬盤緩存同時保存。寫文件到硬盤也在以單獨(dú)NSInvocationOperation完成迂曲,避免拖慢主線程。
18:
SDImageCache在初始化的時候會注冊一些消息通知关霸,在內(nèi)存警告或退到后臺的時候清理內(nèi)存圖片緩存,應(yīng)用結(jié)束的時候清理過期圖片膘掰。
19:
SDWebImage也提供了UIButton+WebCache和MKAnnotationView+WebCache佳遣,方便實(shí)用。
20:
SDWebImagePrefetcher可以預(yù)先下載圖片零渐,方便后續(xù)實(shí)用诵盼。
管理類的使用位置:
這個庫最常用到的是UIImageView的一個分類:UIImageView(WebCache)。
這里面最常用的一個方法就是根據(jù)URL风宁,加載網(wǎng)絡(luò)的圖片。它的實(shí)現(xiàn)如下:
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder{
SDWebImageManager *manager = [SDWebImageManager sharedManager];
// Remove in progress downloader from queue
[manager cancelForDelegate:self];
self.image = placeholder;
if(url){
[manager downloadWithURL:url delegate:self];
}
}
這個方法最大的好處就是扫俺,可以不需要改變UI的類固翰,直接添加網(wǎng)絡(luò)下載功能。
獨(dú)立的異步圖像下載
可能會單獨(dú)用到異步圖片下載疗琉,則一定要用downloaderWithURL:delegate:來建立一個SDWebImageDownloader實(shí)例歉铝。
downloader = [SDWebImageDownloader downloaderWithURL:url delegate:self];
這樣SDWebImageDownloaderDelegate協(xié)議的方法。imageDownloader:didFinishWithImage:被調(diào)用時下載會立即開始并完成柠贤。
獨(dú)立的異步圖像緩存
SDImageCache類提供一個創(chuàng)建空緩存的實(shí)例类缤,并用方法imageForKey:來尋找當(dāng)前緩存。
UIImage *myCachedImage = [[SDImageCache sharedImageCache] imageFromKey:myCacheKey];
存儲一個圖像到緩存的使用方法storeImage:forKey:
[[SDImageCache sharedImageCache] storeImage:myImage forKey:myCacheKey];
默認(rèn)情況下宴霸,圖像將被存儲在內(nèi)存緩存和磁盤緩存中。如果僅僅是想存在內(nèi)存緩存中瓢谢,要是用storeImage:forKey:toDisk:方法的第三個參數(shù)帶一負(fù)值來替代氓扛。
SDWebImage庫的作用:
通過對UIImageView的類別擴(kuò)展來實(shí)現(xiàn)異步加載替換圖片的工作。
主要用到的對象:
1.UIImageView(WebCache)類別采郎,入口封裝尉剩,實(shí)現(xiàn)讀取圖片完成后的回調(diào)毅臊。
2.SDWebImageManager,對圖片進(jìn)行管理的中轉(zhuǎn)站管嬉,記錄那些圖片正在讀取。向下層讀取Cache(調(diào)用SDImageCache)础倍,或者向網(wǎng)絡(luò)讀取對象(調(diào)用SDWebImageDownloader)胎挎。
實(shí)現(xiàn)SDImageCache和SDWebImageDownloader的回調(diào)。
3.SDImageCache德迹,根據(jù)URL的MD5摘要對圖片進(jìn)行存儲和讀取(實(shí)現(xiàn)存在內(nèi)存中或者存在硬盤上兩種實(shí)現(xiàn))揭芍。
實(shí)現(xiàn)圖片和內(nèi)存清理工作。
4.SDWebImageDownloader肌毅,根據(jù)URL向網(wǎng)絡(luò)讀取數(shù)據(jù)(實(shí)現(xiàn)部分讀取和全部讀取后再通知回調(diào)兩種方式)
SDImageCache數(shù)據(jù)管理:
SDImageCache分兩個部分姑原,一個是內(nèi)存層面的,一個是硬盤層面的页衙。
內(nèi)存層面的相當(dāng)是個緩存器,以Key-Value的形式存儲圖片艰躺。當(dāng)內(nèi)存不夠的時候會清楚所有圖片。
用搜索文件系統(tǒng)的方式做管理左电,文件替換方式是以時間為單位页响,剔除時間大于一周的圖片文件。
當(dāng)SDWebImageManager向SDImageCache要資源時栈拖,先搜索內(nèi)存層面的數(shù)據(jù)没陡,如果有就直接返回,沒有的話去訪問磁盤盼玄,將圖片從磁盤讀取出來埃儿,然后做Decoder,將圖片對象放到內(nèi)存層面做備份童番,再返回調(diào)用層。