1. //
  2. // ZZTableViewController.m
  3. // 多图片下载
  4. //
  5. // Created by Mac on 16/1/19.
  6. // Copyright © 2016年 Mac. All rights reserved.
  7. //
  8.  
  9. #import "ZZTableViewController.h"
  10. #import "ZZApp.h"
  11. @interface ZZTableViewController ()
  12. // 用来存放模型
  13. @property (nonatomic, strong) NSArray *apps;
  14.  
  15. @property (nonatomic, strong) NSMutableDictionary *iconDic;
  16.  
  17. // 用于存放下载操作
  18. @property (nonatomic, strong) NSMutableDictionary *operations;
  19.  
  20. @property (nonatomic, strong) NSOperationQueue *queue;
  21.  
  22. @end
  23.  
  24. @implementation ZZTableViewController
  25.  
  26. - (NSOperationQueue *)queue
  27. {
  28. if (!_queue) {
  29. _queue = [[NSOperationQueue alloc] init];
  30.  
  31. }
  32. return _queue;
  33. }
  34.  
  35. - (NSMutableDictionary *)operations
  36. {
  37. if (!_operations) {
  38. _operations = [NSMutableDictionary dictionary];
  39.  
  40. }
  41. return _operations;
  42. }
  43.  
  44. - (NSMutableDictionary *)iconDic{
  45. if (!_iconDic) {
  46. _iconDic = [NSMutableDictionary dictionary];
  47. }
  48. return _iconDic;
  49. }
  50.  
  51. - (NSArray *)apps
  52. {
  53. if (!_apps) {
  54. NSMutableArray *tmpArray = [NSMutableArray array];
  55.  
  56. NSString *path = [[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil];
  57.  
  58. NSArray *dicArray = [NSArray arrayWithContentsOfFile:path];
  59.  
  60. for (NSDictionary *dic in dicArray) {
  61. ZZApp *app = [ZZApp appWithdic:dic];
  62. [tmpArray addObject:app];
  63. }
  64. _apps = tmpArray;
  65. }
  66. return _apps;
  67. }
  68.  
  69. - (void)viewDidLoad {
  70. [super viewDidLoad];
  71.  
  72. }
  73.  
  74. - (void)didReceiveMemoryWarning {
  75. [super didReceiveMemoryWarning];
  76. // Dispose of any resources that can be recreated.
  77. }
  78.  
  79. #pragma mark - Table view data source
  80.  
  81. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  82. //#warning Incomplete implementation, return the number of sections
  83. return ;
  84. }
  85.  
  86. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  87. #warning Incomplete implementation, return the number of rows
  88. return self.apps.count;
  89. }
  90. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  91. {
  92. static NSString *ID = @"app";
  93. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
  94. ZZApp *app = self.apps[indexPath.row];
  95. cell.textLabel.text = app.name;
  96. cell.detailTextLabel.text = app.download;
  97. UIImage *image = self.iconDic[app.icon];
  98.  
  99. if (image) {// 先判断内存中有没有图片
  100. cell.imageView.image = image;
  101. }else{
  102. NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
  103. // 获得文件名
  104. NSString *fileName = [app.icon lastPathComponent];
  105. // 计算出文件全路径
  106. NSString *file = [cachePath stringByAppendingString:fileName];
  107. // 加载沙盒数据
  108. NSData *data = [NSData dataWithContentsOfFile:file];
  109. // 判断沙盒里有没有数据
  110.  
  111. if (data) {// 沙盒中有数据
  112.  
  113. cell.imageView.image = [UIImage imageWithData:data];
  114. // cell.imageView.image =
  115. // 把数据加载到内存里
  116. [self.iconDic setObject:cell.imageView.image forKey:app.icon];
  117.  
  118. }else{// 下载图片
  119. // cell.imageView.image = [UIImage imageNamed:@"屏幕快照 2016-01-19 下午9.54.43"];
  120. // 添加下载操作到字典里
  121. NSOperation *operation = [self.operations objectForKey:app.icon];
  122. if (!operation) {
  123. operation = [NSBlockOperation blockOperationWithBlock:^{
  124. NSURL *url = [NSURL URLWithString:app.icon];
  125. NSData *data = [NSData dataWithContentsOfURL:url];
  126. if (!data) {// 如果下载失败,移除字典里的操作
  127. [self.operations removeObjectForKey:app.icon];
  128. return ;
  129. }
  130.  
  131. // 回到主线程显示图片
  132. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
  133. // cell.imageView.image = [UIImage imageWithData:data];
  134. [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
  135. }];
  136.  
  137. // 放到沙盒里
  138. [data writeToFile:file atomically:YES];
  139.  
  140. // 将图片存到缓存中
  141. [self.iconDic setObject:[UIImage imageWithData:data] forKey:app.icon];
  142.  
  143. // 下载完成,移除操作
  144. [self.operations removeObjectForKey:app.icon];
  145.  
  146. }];
  147. // 添加到队列里面去
  148. [self.queue addOperation:operation];
  149. // 添加到操作字典里去
  150. [self.operations setObject:operation forKey:app.icon];
  151. }
  152. }
  153. }
  154. return cell;
  155. }
  156.  
  157. @end

效果:

1.第一次打开从网络上加载时:

2.第二次打开时,从沙盒中加载:

2016 - 1- 19 利用多线程优化从网上加载图片的Demo的更多相关文章

  1. (Android图片内存优化)Picasso加载图片 教程。。详细版

    Picasso 是 Android 上一个强大的图片下载和缓存库. 示例代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Picasso.with( ...

  2. Listview 异步加载图片之优化篇(有图有码有解释)

    在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...

  3. Listview异步加载图片之优化篇

    在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...

  4. iOS网络加载图片缓存策略之ASIDownloadCache缓存优化

    iOS网络加载图片缓存策略之ASIDownloadCache缓存优化   在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用 ...

  5. android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存

    经常会用到 网络文件 比如查看大图片数据 资源优化的问题,当然用开源的项目  Android-Universal-Image-Loader  或者 ignition 都是个很好的选择. 在这里把原来 ...

  6. requirejs:性能优化-及早并行加载

    为了提高页面的性能,通常情况下,我们希望资源尽可能地早地并行加载.这里有两个要点,首先是尽早,其次是并行. 通过data-main方式加载要尽可能地避免,因为它让requirejs.业务代码不必要地串 ...

  7. android优化从网络中加载图片速度。。

    从网络中加载图片主要要注意两个方面的问题: 1.内存管理:图片占的内存很大,假如图片数量多,很容易让系统抛出out of memory的异常. 同时我们也要注意不同android版本中内存管理的区别. ...

  8. 多线程异步加载图片async_pictures

    异步加载图片 目标:在表格中异步加载网络图片 目的: 模拟 SDWebImage 基本功能实现 理解 SDWebImage 的底层实现机制 SDWebImage 是非常著名的网络图片处理框架,目前国内 ...

  9. Vue优化首屏加载

    背景: 使用vue + iview搭建的一个后台管理系统,路由已经用了懒加载,加载登陆页面,居然还是需要18S左右,刚到一个新公司,项目经理很委婉的说,看看能不能优化了一下.然后就开始了网上一大堆'v ...

随机推荐

  1. 从别人那淘的知识 深入剖析Java中的装箱和拆箱

    (转载的海子的博文   海子:http://www.cnblogs.com/dolphin0520/) 深入剖析Java中的装箱和拆箱 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来 ...

  2. 用过的正则(更新ing)

    http://www.debuggex.com/   这个很好用20120912 //十六进制颜色值的正则表达式 var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6} ...

  3. ARM 汇编的一些规范

    A.5.1  文件格式        ARM 源程序文件(即源文件)为文件格式,可以使用任一文本编辑器编写程序代码.         在一个项目中,至少要有一个汇编源文件或C 程序文件,可以有多个汇编 ...

  4. Redis 学习资料整理

    菜鸟爬坑--Redis学习与探索(二):Redis的数据类型 http://www.cnblogs.com/codediary/archive/2015/02/20/redisstudy-2.html ...

  5. java二维数组简单初步理解

    二维数组 二维数组本质上是以数组作为数组元素的数组,即“数组的数组”. int[][] arr = {{1, 2, 3}, {4, 5, 6}}; System.out.println(arr[0][ ...

  6. Servlet容器如何同时来处理多个请求

    工作者线程Work Thread:执行代码的一组线程调度线程Dispatcher Thread:每个线程都具有分配给它的线程优先级,线程是根据优先级调度执行的Servlet采用多线程来处理多个请求同时 ...

  7. jquery $post $get $

    Jquery在异步提交方面封装的很好,直接用AJAX非常麻烦,Jquery大大简化了我们的操作,不用考虑浏览器的诧异了. 推荐一篇不错的jQuery Ajax 实例文章,忘记了可以去看看,地址为:ht ...

  8. biztalk中使用WCF-SQL接受传送数据【转】

    接触biztalk时间不长,转载一篇学习教程: http://www.cnblogs.com/chnking/archive/2010/05/09/1731098.html chnking写的. 一. ...

  9. [apache]用shell分析网站的访问情况

    随着网站正式运行,我们可以通过通用的免费日志分析工具比如awstats获得一些实际访问网站的信息,例如每天ip量,pv量,用户所用的的浏览器,用户所用的操作系统等,但是有时候希望通过手工方式从WEB日 ...

  10. MongoDB相关资料

    MongoDB的介绍及安装参考http://www.cnblogs.com/lipan/archive/2011/03/08/1966463.html 安装过程: 第一步:下载安装包:官方下载地址←单 ...