第03天多线程网络:(04):多图下载程序内存警告补充
2017-04-20 00:00
295 查看
#####一、多图下载程序内存警告补充
code
LYHAppModel
VC
>>> 当收到内存警告的时候 进行内存清理 - (void)didReceiveMemoryWarning { [self.dict_images removeAllObjects]; [self.queue cancelAllOperations]; // 如果正在下载的话,那么就取消下载 }
code
LYHAppModel
>>>.h #import <Foundation/Foundation.h> @interface LYHAppModel : NSObject /** app的名称 */ @property(nonatomic, strong) NSString *name; /** app的图标 */ @property(nonatomic, strong) NSString *icon; /** app的下载量 */ @property(nonatomic, strong) NSString *download; // 提供一个方法 用于 字典转模型 + (instancetype)LYHAppModelWithDict:(NSDictionary *)dict; @end >>>.m #import "LYHAppModel.h" @implementation LYHAppModel + (instancetype)LYHAppModelWithDict:(NSDictionary *)dict { LYHAppModel *model = [[LYHAppModel alloc]init]; #pragma 字典转模型 几种方式 #pragma mark 1.一个一个转 //model.name = dict["name"]; #pragma mark 2.KVC [model setValuesForKeysWithDictionary:dict]; return model; } @end
VC
#import "ViewController.h" #import "LYHAppModel.h" @interface ViewController () /** 数组源 */ // 如何选择使用 可变还是不可变 是根据需求来说的 // 如果数据是固定的 那么就用 不可变的 // 如果数据是不固定 那么就用 可变的 @property(nonatomic, strong) NSArray *dataA; /** 内存缓存 */ // 每下载完一张图片 要保存起来 @property(nonatomic, strong) NSMutableDictionary *dict_images; /** 队列(用来下载任务) */ @property(nonatomic, strong)NSOperationQueue *queue; /* 图片下载操作缓存 */ @property(nonatomic, strong) NSMutableDictionary *dict_operations; @end @implementation ViewController #pragma mark 懒加载 - (NSMutableDictionary *)dict_operations { if (_dict_operations == nil) { _dict_operations = [NSMutableDictionary dictionary]; } return _dict_operations; } - (NSOperationQueue *)queue { if (_queue == nil) { _queue = [[NSOperationQueue alloc]init]; // 在程序里面 最好只开3~5个队列 // 设置队列并发数 _queue.maxConcurrentOperationCount = 5; } return _queue; } - (NSMutableDictionary *)dict_images { if (_dict_images == nil) { _dict_images = [NSMutableDictionary dictionary]; } return _dict_images; } - (NSArray *)dataA { if (_dataA == nil) { // 字典数组 NSArray *arr = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil]]; NSMutableArray *arrM = [NSMutableArray array]; for (NSDictionary *dict in arr) { [arrM addObject:[LYHAppModel LYHAppModelWithDict:dict]]; } _dataA = arrM; } return _dataA; } - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark --- --- #pragma mark tableViewDataScoure // 多少组 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } // 多少行 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataA.count; } // cell - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 1.创建cell static NSString *ID = @"app"; // 2.设置cell数据 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; // 拿到该行cell的数据 LYHAppModel *model = [self.dataA objectAtIndex:indexPath.row]; // 设置数据 cell.textLabel.text = model.name; cell.detailTextLabel.text = model.download; //2.4 先去内存缓存中,该图片是否存在,如果存在,那么就直接拿到用,否则去检查磁盘缓存 // 如果有磁盘缓存,那么保存一份到内存,设置图片,否则就直接下载 // 1)没有下载过 // 2)重新打开程序 (先去判断内存缓存有没有,没有再去磁盘缓存里面查找,找到了还需要保存到内存缓存里面) UIImage *image = [self.dict_images objectForKey:model.icon]; if (image) { cell.imageView.image = image; NSLog(@"--%zd的图片使用内存缓存图片",indexPath.row); } else { NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; NSString *fileName = [model.icon lastPathComponent]; // 获取文件的最后节点 NSString *fullPath = [caches stringByAppendingPathComponent:fileName]; //NSLog(@" fullPath %@",fullPath); // 检查磁盘缓存(是否存在) NSData *imageData = [NSData dataWithContentsOfFile:fullPath]; // 废除磁盘缓存 imageData = nil; if (imageData) { UIImage *image = [UIImage imageWithData:imageData]; cell.imageView.image = image; NSLog(@"--%zd的图片使用磁盘缓存图片",indexPath.row); // 1.把图片保存到内存缓存 [self.dict_images setObject:image forKey:model.icon]; } else { // 不存在 // 检查该图片是否正在下载(如果是 ,那么什么都不做,否则再添加下载操作) NSBlockOperation *downloadOp = [self.dict_operations objectForKey:model.icon]; if (downloadOp) { // 下载操作 存在 // 什么都不做 } else { // 先清空cell原来的图片 cell.imageView.image = [UIImage imageNamed:@"lyh165"]; // 占位图片 // NSOperationQueue *queue = [[NSOperationQueue alloc]init]; // 1.非主队列 downloadOp = [NSBlockOperation blockOperationWithBlock:^{ NSURL *url = [NSURL URLWithString:model.icon]; NSData *imageData = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:imageData]; // NSLog(@"---download --%@",[NSThread currentThread]); #pragma UI刷新的操作 NSLog(@"%zd---下载-- ",indexPath.row); // 容错处理 // 可能服务器返回的URL不对 if (image == nil) { // 为了服务器能够改过来,我们还需要处理 // 移除当前的key [self.dict_operations removeObjectForKey:model.icon]; return ; } // 演示网速慢的情况 // [NSThread sleepForTimeInterval:2.0]; // 1.把图片保存到内存缓存(演示网速慢的情况 会闪退) [self.dict_images setObject:image forKey:model.icon]; // 线程之间的通信 [[NSOperationQueue mainQueue]addOperationWithBlock:^{ // [self.tableView reloadData]; 刷新整个tableview // 刷新某一行 [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft]; cell.imageView.image = image; // NSLog(@"---UI --%@",[NSThread currentThread]); }]; /* 参数1 : 写到那个位置 参数2 : 表示原子性 */ [imageData writeToFile:fullPath atomically:YES]; // 图片下载完之后,移除下载操作 [self.dict_operations removeObjectForKey:model.icon]; }]; // 2.封装操作 // 添加操作 到 操作缓存中 [self.dict_operations setObject:downloadOp forKey:model.icon]; // 3.添加操作到队列中 [self.queue addOperation:downloadOp]; } } } return cell; } // http://p16.qhimg.com/dr/48_48_/t0125e8d438ae9d2fbb.png (图1正确连接) // http://p16.qhimg.com/dr/48_48_/t0125e8d438ae9d2fb.png (错误连接 正在使用) /* 1.UI很不流畅 (因为放到主线程里面) ---> 开启子线程下载图片 2.图片被重复下载 ---> 先把之前已经下载的图片保存起来(字典) 内存缓存 ---> 磁盘缓存(保存到沙盒里面) 3.图片不会刷新(解决) 4.图片重复下载(图片下载需要时间,当图片还未完全下载之前,又要重新显示该图片) 图片的下载操作 添加两到三次 --->[添加操作缓存] 5.数据错乱 --->(设置占位图片) */ - (void)didReceiveMemoryWarning { [self.dict_images removeAllObjects]; [self.queue cancelAllOperations]; // 如果正在下载的话,那么就取消下载 } @end
相关文章推荐
- 第03天多线程网络:(03):多图下载程序完善
- 第03天多线程网络:(01):多图下载程序缓存处理
- 第03天多线程网络:(11):多图下载程序应用NSCache
- 第03天多线程网络:(02):多图下载程序开子线程下载图片
- 为什么象网络蚂蚁这样的多线程程序可以加快下载速度?
- 第03天多线程网络:(06):多线程知识点补充
- 用VB编写异步多线程下载程序
- 用VB编写异步多线程下载程序
- 程序网络工作组ASP站点管理员(ASPAdmin) V1.02 下载
- 一个简单的多线程、断点下载Java程序
- Java Socket 编程——多线程网络聊天程序
- JAVA写的多线程下载程序,并具有断点续传功能
- Android(五)数据存储之五网络多线程断点下载
- 网络通信程序一定得多线程
- 用java编写多线程ftp断点下载文件程序
- 一个根据断点续传原理而实现的多线程下载的程序
- Windows Forms 实现安全的多线程详解(附带程序代码示例) (摘自网络)
- C++ Builder 编写多线程下载程序
- 多线程下载地图切片程序(更新)
- 多核机器上多线程内存敏感程序的可伸缩性