多线程异步加载图片

author author     2022-08-28     631

关键词:

多图片多线程异步下载


开发中非常常用的就是就是图片下载,我们常用的就是SDWebImage,但是作为开发人员,不仅要能会用,还要知道其原理。本文就会介绍多图下载的实现。

本文中的示例Demno地址,下载后项目位于iOS_Demo/09-多图片多线程下载

1 - 问题

开篇我就先将多图下载过程中出现的问题摆出来,让我们能够一一克服

1:下载过程要放到子线程中,否则会导致UI线程卡顿
2:图片会重复下载,我们不仅要把下载完的图片放到内存中,还要把下载队列也缓存起来,否则可能图片没有下载完,会多次创建下载队列
3:沙盒缓存,放到哪里,根据下面对沙盒文件的介绍我们需要把图片放到Library/Caches目录下。

Document : iTunes会备份
Library : 
        1:Caches:缓存文件,不会清除
        2:Preferences:偏好设置,保存账号信息
tmp :临时路径,随时会被删除,临时的不是重要的数据

下载流程图

明白了问题后,我们需要制定战略(画流程图),这样根据流程图,下载过程就更为清晰明了。

技术分享

根据流程图一些坑,我们就可以完美的避免掉了。这样写程序也更有章法。

2 - 开始下载图片

根据前面的介绍,我们需要有两个缓存对象:

  1. 图片data的内存缓存
  2. 下载队列的缓存

我们可以使用NSMutableDictionary进行缓存,

这里我们假设两个缓存对象分别是:

/** 内存中图片的缓存字典 */
@property (nonatomic,strong)NSMutableDictionary * memoryImages;
 
/** 下载操作的字典 */
@property (nonatomic,strong)NSMutableDictionary * operations;

2.1 内存缓存中取值

所以下载前,我们先要到内存中取值

   NSData *imageData = [self.memoryImages objectForKey:url];

如果imageData对象存在,我们就直接设置到Cell上。

2.2 内存缓存中没有,我们到沙盒中取值

内存缓存中不存在时我们到沙盒中进行查看:

        NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
    //获取图片名字,图片名称不能包含URL,
    NSString *fileName = [url lastPathComponent];
    NSString *filePaPath  = [path stringByAppendingPathComponent:fileName];

    //内存中没有图片的缓存 -- 从沙盒中取出
    NSData *imageData = [NSData dataWithContentsOfFile:filePaPath];
    

如果图片存在,我们需要把图片设置到Cell上,并且放一份到内存缓存中

//沙盒中取出后,放一份到内存缓存中
[self.memoryImages setObject:imageData forKey:url];

这样下次就不用频繁访问沙盒了。

2.2 内存缓存中没有,沙盒中也没有,我们需要判断下载队列是否已经存在

如果网速慢一些,并且Cell上下滑动的频率快一些的话,假如第一次第5行的Cell显示的时候,内存缓存中没有,沙盒中也没有,这时我们创建了下载对象,然后这行Cell被滑出屏幕,再次进来的时候图片还是没有下载完毕,经过判断内存缓存中没有,沙盒中也没有,我们如果再次创建下载对象的话,就会重复下载图片了,所以我们要把下载队列也进行缓存,当内存缓存中没有,沙盒中也没有时,我们先判断下载队列中是否已经存在了。

这里使用的是NSBlockOperation
NSBlockOperation *doo = [self.operations objectForKey:url];

2.2 内存缓存中没有,沙盒中也没有,下载队列也没有

这时我们就需要创建下载对象进行下载了。

首先我们先可以设置一个占位图,这样的显示更为友好一下。

 NSBlockOperation *downO = [NSBlockOperation blockOperationWithBlock:^{
                NSURL *uurl = [NSURL URLWithString:url];
                
                NSURLSession *session = [NSURLSession sharedSession];
                NSURLSessionDataTask *down = [session  dataTaskWithURL:uurl completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                //图片的下载过程    
                 
                }];
                
                [down resume];
            }];

同时加入下载队列

  //下载对象加入队列中
 [self.operations setObject:downO forKey:url];
 [self.queue addOperation:downO];

图片下载完毕后,我们需要

//把图片data存入内存中
[self.memoryImages setObject:data forKey:url];

//同时写入沙盒中,永久缓存
[data writeToFile:filePaPath atomically:YES];

同时在主线程中更新UI

 [[NSOperationQueue mainQueue] addOperationWithBlock:^{
   
 UIImage *image = [UIImage imageWithData:data];
 cell.iconView.image = image;
 [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}];




多线程编程——anr

1、为什么要用多线程这里列出几个原因:提高用户体验或者避免ANR:在事件处理代码中需要使用多线程,否则会出现ANR(Applicationisnotresponding),或者因为响应较慢导致用户体验很差。异步:应用中有些情况下并不一定需要同步阻... 查看详情

继承thread类实现多线程简单实例(代码片段)

继承Thread类实现多线程简单实例文章目录继承Thread类实现多线程简单实例一、多线程的意义二、多线程的创建三、代码一、多线程的意义1.为什么要使用多线程(a)提高用户体验或者避免ANR在事件待处理码中需要使用多... 查看详情

python爬虫asyncioaiohttpaiofiles单线程多任务异步协程爬取图片(代码片段)

python爬虫asyncioaiohttpaiofiles多任务异步协程爬取图片main.py"""===coding:UTF8==="""#requests.get()同步代码->异步操作aiohttpimportasyncioimportaiohttpimportaiofilesurls&# 查看详情

androidstudio添加本地图片

...个开源项目的主要功能和使用:  一、功能概要  多线程图片加载;  灵活更改ImageLoader的基本配置,包括最大线程数、缓存方式、图片显示选项等;  图片异步加载缓存机制,包括内存缓存(软引用)及本地缓存; ... 查看详情

spring多线程异步上传图片处理水印缩略图(代码片段)

点击关注公众号,实用技术文章及时了解使用环境SpringBoot+FastDfs+thumbnailatorfdfs环境自己搞吧thumbnailatormaven依赖:<dependency>    <groupId>net.coobird</groupId>    <artifactId>thumbna 查看详情

androidhandler异步消息处理机制的妙用创建强大的图片加载类

...GridView实现手机的相册功能,一般会用到LruCache,线程池,任务队列等;那么异步消息处理可以用哪呢?1、用于UI线程当Bitmap加载完成后更新ImageView2、在图片加载类初始化时,我们会在一个子线程中维护一... 查看详情

图片加载框架之imageloader

...是Universal-Image-Loader,该项目可以在于Github搜索到.特征:多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等支持随意的配置ImageLoade 查看详情

多线程本地图片加载示例opencvpthread

Pthreadbarrier的简单使用示例:C++代码如下://ThreadingLoadImages.cpp:定义控制台应用程序的入口点。//#include"stdafx.h"#include<pthread.h>#include<opencv2/opencv.hpp>#defineTHREADS3//Barriervariablepthread_b 查看详情

androidhandler异步消息处理机制的妙用创建强大的图片加载类

...GridView实现手机的相册功能,一般会用到LruCache,线程池,任务队列等;那么异步消息处理可以用哪呢?1、用于UI线程当Bitmap加载完 查看详情

jsfilereader图片加载

...于将文件内容读入内存,通过一系列异步接口,可以在主线程中访问本地文件。方法方法定义描述abort():void终止文件读取操作readAsArrayBuffer(file):void异步按字节读取文件内容,结果用ArrayBuffer对象表示readAsBinaryString(file):void异步按... 查看详情

android开发之asynctask

...调用一次getView启动一个异步),这样会报错的(开启的线程多了什么的问题)。官方上得解决方法是:将AsyncTask也弄成了弱引用,这样就能及时回收了,具体操作你可以去看文档,有点复杂,这里解释不清。我采用的是另一种... 查看详情

image-universal-loader

ImageLoader简介和使用方法1.功能概要(1).使用多线程加载图片(2).灵活配置ImageLoader的基本参数,包括线程数、缓存方式、图片显示选项等;(3).图片异步加载缓存机制,包括内存缓存及SDCard缓存;(4).采用监听器监听图片加载过程及... 查看详情

javascript异步加载(代码片段)

js特点:单线程异步 (其实就是多线程,只是说用异步的方式表现出来了而已)同步的会阻塞代码,在html中,只有script标签中的src会阻塞代码,可以通过defer属性和async属性进行解决JavaScript的异步加载:异步加载又叫非阻塞... 查看详情

android中常见的线程池(代码片段)

Android中常见的线程池Executors在Android中什么场景下使用Executors是Java平台的一个工具类,提供了方便的线程池管理功能,可以帮助开发者更加便捷地管理线程。在Android开发中,Executors经常被用于异步处理任务,特别是在处理IO操作... 查看详情

异步多线程

UI只能在主线程中完成更新,在子线程中更新UI报错如下Onlytheoriginalthreadthatcreatedaviewhierarchycantouchitsviews.但是,在主线程中完成耗时操作容易引起使用体验不佳,进程卡顿问题,为了解决此问题引入异步多线程 异步多线程 查看详情

异步与多线程

异步线程线程池Task的使用异步与线程的区别 查看详情

qml性能优化(来源于群友分享);

...化使用时间驱动避免定时轮询;使用信号槽形式;使用多线程C++;QMLWorkerScript元件;使用QtQuickCompiler只需要再PRO文件中添加一行:CONIFG+=qtquickcompiler避免使用CPU渲染的元件;Canvas、QtCharts;使用异步加载图片异步加载使用C++处理大数... 查看详情

异步多线程二

  查看详情