【转载】基于AFNetWorking3.0的图片缓存分析
原文出處:Yasin的簡書?http://www.jianshu.com/p/b1045c3fc8d0
?
圖片在APP中占有重要的角色,對圖片做好緩存是重要的一項工作。
[TOC]
理論
不喜歡理論的可以直接跳到下面的Demo實踐部分
緩存介紹
緩存按照保存位置可以分為兩類:內存緩存、硬盤緩存(FMDB、CoreData...)。
我們常說的數據緩存包含內存緩存、硬盤緩存和網絡請求URL緩存。其中網絡請求URL緩存也包含內存緩存和硬盤緩存。
圖片緩存思路
URL緩存(緩存請求)
網絡請求除了客戶端需要做簡單的配置外,最主要需要服務器支持,服務端也很簡單,只需要在response里面設置Cache-Control字段就行了.
最常見的URL緩存實現方式:NSURLCache。NSURLCache可以在memory 和 disk 上緩存。
AFNetWorking是基于NSURLSession(iOS7以上的網絡請求框架),在生成配置的時候有三種配置選擇
也就是說default同時實現了內存緩存和硬盤緩存,ephemeral實現了內存緩存,對于圖片下載我們當然選擇default。
我們還可以對緩存的大小進行設置,只需要對NSURLCache進行初始化就可以了
實現初始化
在-application:didFinishLaunchingWithOptions:中對[NSURLCache sharedURLCache]進行初始化設置:
1 NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 2 diskCapacity:20 * 1024 * 1024 3 diskPath:nil]; 4 [NSURLCache setSharedURLCache:URLCache];也可以單獨對NSURLSession的configuration進行設置,
在AFNetWorking中對于圖片網絡請求設置了20M的內存緩存和150M的硬盤緩存:
緩存策略
緩存策略是指對網絡請求緩存如果處理,是使用緩存還是不使用
1 NSURLRequestUseProtocolCachePolicy: 對特定的 URL 請求使用網絡協議中實現的緩存邏輯。這是默認的策略。 2 NSURLRequestReloadIgnoringLocalCacheData:數據需要從原始地址加載。不使用現有緩存。 3 NSURLRequestReloadIgnoringLocalAndRemoteCacheData:不僅忽略本地緩存, 4 同時也忽略代理服務器或其他中間介質目前已有的、協議允許的緩存。 5 NSURLRequestReturnCacheDataElseLoad:無論緩存是否過期,先使用本地緩存數據。 6 如果緩存中沒有請求所對應的數據,那么從原始地址加載數據。 7 NSURLRequestReturnCacheDataDontLoad:無論緩存是否過期,先使用本地緩存數據。 8 如果緩存中沒有請求所對應的數據,那么放棄從原始地址加載數據, 9 請求視為失敗(即:“離線”模式)。 10 NSURLRequestReloadRevalidatingCacheData:從原始地址確認緩存數據的合法性后, 11 緩存數據就可以使用,否則從原始地址加載。在AFNetWorking中同樣對configuration進行設置
1 configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;如果你繼承AFImageDownloader重新實現了他的初始化,requestCachePolicy注意AFImageDownloader中只有三種才設置了緩存
1 case NSURLRequestUseProtocolCachePolicy: 2 case NSURLRequestReturnCacheDataElseLoad: 3 case NSURLRequestReturnCacheDataDontLoad:圖片內存緩存
AFNetWorking3.0放棄了NSCache作為圖片內存緩存管理,這讓我非常不解。
有人說它的性能和 key 的相似度有關,如果有大量相似的 key (比如 "1", "2", "3", ...),NSCache 的存取性能會下降得非常厲害,大量的時間被消耗在 CFStringEqual() 上,不知這是不是放棄使用NSCache的原因。
AFNetWorking3.0的圖片緩存類貌似是基于這個理論來做內存大小管理的(之前AF的內存大小計算方法有錯,我修改了一下提交了,現在已經審核通過合并進去了,哈哈哈哈哈,我也算是貢獻過AF了)。AFNetWorking2.x中還是使用AFImageCache進行memory上緩存。
NSCache在memory上緩存,類似于NSMutableDictionary ,以 哈希算法 管理。有自動清理機制,當緩存到memory時,如果memory空間不夠,則會自動刪除memory中當前界面不使用的空間。
AFAutoPurgingImageCache使用NSMutableDictionary <NSString* , AFCachedImage*>進行內存緩存映射,并進行管理,當內存警告時就清空NSMutableDictionary。如果內存占用超過限制,則按照時間順序進行刪除。
圖片硬盤緩存
就是我們常說的把數據保存在本地,比如FMDB、CoreData、歸檔、NSUserDefaults、NSFileManager等等,這里就不多說了。
AFNetWorking3.0沒有直接做圖片硬盤緩存,而是通過URL緩存做的硬盤緩存。也就是說,如果內存緩存沒有讀取到圖片,就會調用下載邏輯,通過下載緩存的內存緩存硬盤緩存來獲取到已下載過的圖片,如果沒有下載過,就會重新下載。
如果我們自己做圖片硬盤緩存建議使用NSFileManager,因為一般圖片data會比較大,測試證明路徑緩存會比放在數據庫有更高的性能。
實踐
Demo下載
?
使用NSURLSession做網絡請求緩存。
1 NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; //使用default配置,自帶網絡請求緩存 2 [config setHTTPAdditionalHeaders:@{@"Accept":@"image/*"}];//設置網絡數據格式 3 NSURLSession *session = [NSURLSession sessionWithConfiguration:config]; 4 NSURLRequest *request = [NSURLRequest requestWithURL:url]; 5 WEAKSELF 6 NSURLSessionDataTask *task = [session dataTaskWithRequest:request 7 completionHandler:^(NSData * _Nullable data, 8 NSURLResponse * _Nullable response, NSError * _Nullable error) { 9 //使用’獲取數據(NSURLSessionDataTask)‘的方式發起請求 10 UIImage *image = [UIImage imageWithData:data]; 11 dispatch_async(dispatch_get_main_queue(), ^{ 12 weakSelf.imageView.image = image; 13 }); 14 }]; 15 [task resume];我們通過連續兩次下載圖片可以發現defaultSessionConfiguration下NSURLSession會自動做網絡請求緩存。
使用AFNetWorking下載圖片
導入頭文件#import "UIImageView+AFNetworking.h"
使用特別簡單,只有一行代碼:[imageView setImageWithURL:url];
UIImageView+AFNetworking做了內存緩存和基于NSURLSession的網絡請求緩存,并沒有做硬盤緩存,估計是考慮到圖片的網絡請求硬盤緩存足以滿足需要,所以省略了額外的硬盤緩存,內存緩存加快了讀取速度,這個是非常有必要的。
進入UIImageView+AFNetworking代碼分析:
?
1 if ([urlRequest URL] == nil) { 2 [self cancelImageDownloadTask]; 3 self.image = placeholderImage; 4 return; 5 } 6 //如果新傳入的URL為空則取消圖片下載并設置圖片為默認圖 1 if ([self isActiveTaskURLEqualToURLRequest:urlRequest]){ 2 return; 3 } 4 //如果新傳入的URL與當前URL相同則直接返回,否則取消當前下載,重新進行圖片查找下載 UIImage *cachedImage = [imageCache imageforRequest:urlRequest withAdditionalIdentifier:nil]; //從內存緩存中讀取image,如果沒有則發起新的請求 1 AFImageDownloader *downloader = [[self class] sharedImageDownloader]; 2 //使用單例下載,內存緩存為downloader.imageCache 3 //downloader設置的網絡請求20M的內存緩存和150M的硬盤緩存 4 //downloader設置的網絡請求緩存策略為NSURLRequestUseProtocolCachePolicy 5 //imageCache設置了內存60M最大100M 6 //網絡請求發起前會再次判斷imageCache中是否含有該image測試
使用Charles查看圖片下載的網絡請求發生了幾次,判斷緩存是否成功。
其中硬盤緩存需要寫入時間,網絡請求完成后略等一下,否則硬盤緩存不會生效
設置默認網絡緩存大小
如果沒有對NSURLRequest的URLCache進行設置,默認是使用[NSURLCache sharedURLCache],所以如果有需要可以如下設置
1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 2 // Override point for customization after application launch. 3 [AFNetworkActivityIndicatorManager sharedManager].enabled = YES; 4 //網絡請求時狀態欄網絡狀態小轉輪 5 6 NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 7 diskCapacity:20 * 1024 * 1024 8 diskPath:nil]; 9 //內存4M,硬盤20M 10 [NSURLCache setSharedURLCache:URLCache]; 11 12 return YES; 13 } 文/Yasin的簡書(簡書作者)原文鏈接:http://www.jianshu.com/p/b1045c3fc8d0
著作權歸作者所有,轉載請聯系作者獲得授權,并標注“簡書作者”。
轉載于:https://www.cnblogs.com/iOSClub/p/5468027.html
總結
以上是生活随笔為你收集整理的【转载】基于AFNetWorking3.0的图片缓存分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mac Path had bad own
- 下一篇: redirect_uri参数错误解决方法