国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

iOSCell異步圖片加載優化,緩存機制詳解

2019-11-14 18:29:13
字體:
來源:轉載
供稿:網友

最近研究了一下UITbleView中異步加載網絡圖片的問題,iOS應用經常會看到這種界面。
一個tableView上顯示一些標題、詳情等內容,在加上一張圖片。
這里說一下這種思路。

為了防止圖片多次下載,我們需要對圖片做緩存,緩存分為內存緩存于沙盒緩存,我們當然兩種都要實現。
由于tableViewCell是有重用機制的,也就是說,內存中只有當前可見的cell數目的實例,滑動的時候,新顯示cell會重用被滑出的cell對象。這樣就存在一個問題:

一般情況下在我們會在cellForRow方法里面設置cell的圖片數據源,也就是說如果一個cell的imageview對象開啟了一個下載任務,這個時候該cell對象發生了重用,新的image數據源會開啟另外的一個下載任務,由于他們關聯的imageview對象實際上是同一個cell實例的imageview對象,就會發生2個下載任務回調給同一個imageview對象。這個時候就有必要做一些處理,避免回調發生時,錯誤的image數據源刷新了UI。

所以在我們向下滑動tableview的時候我們需要手動去取消掉下載操作,當用戶停止滑動,再去執行下載操作。SDWebImage采用的也是這種策略。

很簡單我們只需要監聽ScrollView的代理方法(tableview繼承自Scrollview)。

/** *  當用戶開始拖拽表格時調用 */- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{    // 暫停下載    [self.queue setSuspended:YES];}/** *  當用戶停止拖拽表格時調用 */- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{    // 恢復下載    [self.queue setSuspended:NO];}

而SDWebImage才用的就是這種方式,所以在運行SDWebImage的demo的時候,可以看到,如果快速滑下去,然后又滑回來的話,圖片是過了一會才顯示出來,這是因為快速滑動的時候,舊數據源的下載任務被取消掉了。
/-------------------------------------------

下面介紹一下具體的思路。
異步下載圖片我們用的是NSOperation,并且創建一個全局的queue來管理下載圖片的操作。

/** *  存放所有下載操作的隊列 */@PRoperty (nonatomic,strong) NSOperationQueue* queue;

另外需要兩個字典operations、images

/** *  存放所有的下載操作(url是key,operation對象是value) */@property (nonatomic,strong) NSMutableDictionary* operations;/** *  存放所有下載完成的圖片,用于內存緩存,同樣用Url為key */@property (nonatomic,strong) NSMutableDictionary* images;

在把圖片顯示到Cell上之前
先判斷內存中(images字典中)有沒有圖片,
如果有,則取出url對應的圖片來顯示,
如果沒有,再去沙盒緩存中查看,當然存到沙盒中都是NSData。
如果沙盒緩存中有,我們取出對應的數據給Cell去顯示
如果沙盒中也沒有圖片,我們先顯示占位圖片。再創建operation去執行下載操作了。
當然在創建operation之前,我們要判斷這個operation操作是否存在
這個時候就用到我們operations這個字典了

//取出當前URL對應的下載操作NSBlockOperation* operation = self.operations[app.icon];

如果沒有下載操作,我們才需要真正的去創建operation執行下載。
創建好下載操作之后應該把該操作存放到全局隊列中去異步執行,同時吧操作放入operations字典中記錄下來。

//添加操作到隊列中  [self.queue addOperation:operation];//添加到字典中   self.operations[app.icon] = operation;

下載完成之后:
把下載好的圖片放到內存中、同時存到沙盒緩存中
下面存放到沙盒中的代碼可以定義成宏,具體可以下載后面的demo

if (image) { //防止下載失敗為空賦值造成崩潰  vc.images[app.icon] = image;  //下載完成的圖片存入沙盒中                      // UIImage --> NSData --> File(文件)     NSData* ImageData = UIImagePNGRepresentation(image);     NSString* CachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];     NSString* filePath = [CachesPath stringByAppendingPathComponent:[app.icon lastPathComponent]];     [ImageData writeToFile:filePath atomically:YES];           }

執行完上面的操作之后回到主線程刷新表格,
從operations字典中移除下載操作(防止operations越來越大,同時保證下載失敗后,能重新下載)

//刷新當前行的圖片數據  self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

這里我們不用[self.tableView reloadata],因為會刷新整個cell,浪費性能。

當然如果你的下載操作里面需要做的事情很多的時候,可以考慮自定義operation。 由于我這里只是簡單的下載小圖就沒有自定義operation了。注意要自己創建自動釋放池。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 望都县| 和林格尔县| 巍山| 泰安市| 夹江县| 色达县| 丹寨县| 乳源| 邯郸市| 锦屏县| 蓝山县| 蕉岭县| 友谊县| 简阳市| 兰坪| 高清| 梁山县| 子洲县| 玛多县| 石台县| 佳木斯市| 合江县| 绥棱县| 曲周县| 汉中市| 平阴县| 杭锦后旗| 仁化县| 通许县| 中山市| 胶州市| 江西省| 莱西市| 淅川县| 汕尾市| 托克托县| 锡林郭勒盟| 临洮县| 吉林省| 义马市| 贞丰县|