• iOS开发网络多线程之多图下载


    一. 多线程中多图片下载

    头像通过网络下载得到

    效果图如下:

    二. 设计思路

        利用tableView实现多行数据的现实,图标通过网络下载很耗时,需要在子线程中执行.

        cell中的ImageView的设置:

    1. 首先到图片缓存池中取(定义一个存放图片的的字典属性),如果有直接设置;

    2. 如果图片缓存池没有,再到沙盒缓存cache中查看是否存在,如果有直接设置,并把沙盒中的图片写入到图片缓存池中

    3. 如果沙盒cache中也没有,就需要开线程下载;

    4. 首先判断当前图片是否有任务在下载(定义一个存放任务的字典属性);

    5. 如何没有当前没有任务在下载,就开启一个子线程进行数据下载

    6. 下载得到一个图片

        6.1 这时需要优化,考虑到图片路径不对或者网络比较差,下载图片失败,得到的图片为空,这时需要判断如果为空就直接return,并把此任务从缓存池中移除

    7. 下载的图片写入到图片缓存池中

    8. 下载的图片同时写入到沙盒中

    9. 在主线程中刷新数据

    10. 将操作添加到任务缓存池中

    11. 队列中添加操作

    1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    2. {
    3. static NSString *ID = @"APP";
    4. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    5. if (!cell) {
    6. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    7. }
    8. LDApp *app = self.apps[indexPath.row];
    9. cell.textLabel.text = app.name;
    10. cell.detailTextLabel.text = app.download;
    11. /*
    12. 1.先到缓存中查看有没有图片,判断如有直接设置
    13. 2.如果没有进入沙盒中查看是否有icon中的后缀图片,如有直接取出设置,并写入到缓存中
    14. 3.如果没有则下载,则查看队列中是否有此下载任务,如果没有就下载完成之后设置并写入到缓存中
    15. */
    16. // 1.从图片缓存池中取出图片
    17. UIImage *image = self.cacheDict[app.icon];
    18. if (image) {
    19. cell.imageView.image = image;
    20. NSLog(@"从缓存池中加载图片-%zd", indexPath.row);
    21. } else {
    22. // 获取沙盒缓存路径
    23. NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    24. // 截取app名称字符串
    25. NSString *appName = [app.icon lastPathComponent];
    26. // 拼接路径
    27. NSString *appCachePath = [cachePath stringByAppendingPathComponent:appName];
    28. // 加载沙盒路径图片
    29. NSData *data = [NSData dataWithContentsOfFile:appCachePath];
    30. // 判断沙盒路径图片是否存在
    31. if (data) { // 存在
    32. NSLog(@"从沙盒中加载图片-%zd", indexPath.row);
    33. // 直接设置
    34. cell.imageView.image = [UIImage imageWithData:data];
    35. // 写入缓存中
    36. [self.cacheDict setObject:cell.imageView.image forKey:app.icon];
    37. } else { // 沙盒不存在,进行下载
    38. // 设置一个占位图
    39. cell.imageView.image = [UIImage imageNamed:@"t012fea7312194537c2"];
    40. // 判断任务缓存池中是否存在下载此app图片的任务
    41. NSBlockOperation *operation = self.operationDict[app.icon];
    42. if (operation == nil) { // 任务缓存池中没有此任务才进行下载
    43. // 封装任务
    44. operation = [NSBlockOperation blockOperationWithBlock:^{
    45. NSLog(@"下载图片-%zd", indexPath.row);
    46. // 获取图片URL
    47. NSURL *url = [NSURL URLWithString:app.icon];
    48. // 加载二进制
    49. NSData *data = [NSData dataWithContentsOfURL:url];
    50. // 将二进制转为图片
    51. UIImage *image = [UIImage imageWithData:data];
    52. // 加载的图片路径不正确或者网速慢下载的图片为空即为下载失败,直接return
    53. if (image == nil) {
    54. // 将任务移除,如果不移除下次就不能进入进行下载,因为当前操作在任务缓存池中
    55. [self.operationDict removeObjectForKey:app.icon];
    56. return;
    57. }
    58. // 将图片加入到图片缓存池中
    59. self.cacheDict[app.icon] = image;
    60. // 将图片写入到沙盒中
    61. [data writeToFile:appCachePath atomically:YES];
    62. // 刷新UI
    63. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
    64. //cell.imageView.image = image;
    65. // 局部刷新
    66. [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
    67. // 下载完成之后将任务移除任务池
    68. [self.operationDict removeObjectForKey:app.icon];
    69. }];
    70. }];
    71. // 任务加入到缓存池中
    72. self.operationDict[app.icon] = operation;
    73. [self.queue addOperation:operation];
    74. }
    75. }
    76. }
    77. return cell;
    78. }


    三.第三方框架(SDWebImage)

    1. 多图下载

    第一个参数: 图片的URL路径

    第二个参数: 占位图片

    1. // 第三方框架下载多图
    2. [cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@"t012fea7312194537c2"]];


    2. 内存告警清除缓存

    清除缓存数据,在applictionDelegate中执行缓存清除

    引入"SDWebImageManager.h"头文件

    -(void)applicationDidReceiveMemoryWarning:(UIApplication *)application方法中进行对缓存数据清除

    获取图片管理单例执行cancelAll法进行缓存清除

    cancelAll方法内部已经实现了clearDisk方法

    1. #import "AppDelegate.h"
    2. #import "SDWebImageManager.h"
    3. @interface AppDelegate ()
    4. @end
    5. @implementation AppDelegate
    6. -(void)applicationDidReceiveMemoryWarning:(UIApplication *)application
    7. {
    8. //当发生内存警告的时候如何处理
    9. //1.取消当前正在下载的所有操作
    10. [[SDWebImageManager sharedManager] cancelAll];
    11. //2.图片缓存处理
    12. /*
    13. kDefaultCacheMaxCacheAge:默认缓存周期是一周
    14. maxCacheSize:
    15. cleanDisk:找到缓存文件,先删除过期缓存,统计当前缓存文件的大小(currentSzie),如果发现大于最大缓存数量(currentSzie>maxCacheSize),那么会继续删除,按照缓存文件产生的事件顺序,从远到进删除,直到小于为止
    16. clearDisk:直接删除,然后创建新的文件夹
    17. */
    18. //内部已经实现了
    19. // [[SDWebImageManager sharedManager].imageCache clearDisk];
    20. }
    21. @end


  • 相关阅读:
    Android 编程代码手机定位
    Android 编程下快捷图标的创建
    Android 编程技巧设置 ADB 连接超时时间
    Android 编程下获得应用程序的签名
    Android 编程下如何获取有 Internet 访问权限的应用
    Android 编程下通知的发送
    Androidpn 消息推送总结
    Json 和 Jsonlib 的使用
    asp.net 控件不显示,提示无法找到
    做一课永远成长的苹果树!
  • 原文地址:https://www.cnblogs.com/Xfsrn/p/5000313.html
Copyright © 2020-2023  润新知