博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS异步图片加载优化与常用开源库分析
阅读量:5870 次
发布时间:2019-06-19

本文共 1940 字,大约阅读时间需要 6 分钟。

网络图片显示大体步骤:

1、下载图片;

2、图片处理(裁剪,边框等);

3、写入磁盘;

4、从磁盘读取数据到内核缓冲区;

5、从内核缓冲区复制到用户空间(内存级别拷贝);

6、解压缩为位图(耗cpu较高);

7、如果位图数据不是字节对齐的,CoreAnimation会copy一份位图数据并进行字节对齐;

8、CoreAnimation渲染解压缩过的位图。

以上4、5、6、7、8步是在UIImageView的setImage时进行的,所以默认在主线程进行(iOS UI操作必须在主线程执行)。

一些优化思路: 

异步下载图片;

image解压缩放到子线程;

使用缓存(包括内存级别和磁盘级别);

存储解压缩后的图片,避免下次从磁盘加载的时候再次解压缩;

减少内存级别的拷贝(针对第5点和第7点);

良好的接口(比如SDWebImage使用category);

Core Data vs 文件存储;

图片预下载。

关于异步图片下载:

 fastImageCache主要针对于从磁盘文件读取并展示图片的极端优化,所以并没有集成异步图片下载的功能。这里主要来看看SDWebImage(AFNetWorking的基本类似)的实现方案。

 tableView中,异步图片下载任务的管理:

 我们知道,tableViewCell是有重用机制的,也就是说,内存中只有当前可见的cell数目的实例,滑动的时候,新显示cell会重用被滑出的cell对象。这样就存在一个问题。

 一般情况下在我们会在cellForRow方法里面设置cell的图片数据源,也就是说如果一个cell的imageview对象开启了一个下载任务,这个时候该cell对象发生了重用,新的image数据源会开启另外的一个下载任务,由于他们关联的imageview对象实际上是同一个cell实例的imageview对象,就会发生2个下载任务回调给同一个imageview对象。这个时候就有必要做一些处理,避免回调发生时,错误的image数据源刷新了UI。

 

SDWebImage提供的UIImageView扩展的解决方案:

 imageView对象会关联一个下载列表(列表是给AnimationImages用的,这个时候会下载多张图片),当tableview滑动,imageView重设数据源(url)时,会cancel掉下载列表中所有的任务,然后开启一个新的下载任务。这样子就保证了只有当前可见的cell对象的imageView对象关联的下载任务能够回调,不会发生image错乱。

 同时,SDWebImage管理了一个全局下载队列(在DownloadManager中),并发量设置为6.也就是说如果可见cell的数目是大于6的,就会有部分下载队列处于等待状态。而且,在添加下载任务到全局的下载队列中去的时候,SDWebImage默认是采取LIFO策略的,具体是在添加下载任务的时候,将上次添加的下载任务添加依赖为新添加的下载任务。        

[wself.downloadQueue addOperation:operation];        if (wself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {            // Emulate LIFO execution order by systematically adding new operations as last operation's dependency            [wself.lastAddedOperation addDependency:operation];            wself.lastAddedOperation = operation;        }

 

 另外一种解决方案是:

 imageView对象和图片的url相关联,在滑动时,不取消旧的下载任务,而是在下载任务完成回调时,进行url匹配,只有匹配成功的image会刷新imageView对象,而其他的image则只做缓存操作,而不刷新UI。

 同时,仍然管理一个执行队列,为了避免占用太多的资源,通常会对执行队列设置一个最大的并发量。此外,为了保证LIFO的下载策略,可以自己维持一个等待队列,每次下载任务开始的时候,将后进入的下载任务插入到等待队列的前面。

 

iOS异步任务一般有3种实现方式:

 

  • NSOperationQueue

  • GCD

  • NSThread

     

这几种方式就不细说了,SDWebImage是通过自定义NSOperation来抽象下载任务的,并结合了GCD来做一些主线程与子线程的切换。

转载地址:http://cjxnx.baihongyu.com/

你可能感兴趣的文章
Java探索之旅(11)——抽象类与接口
查看>>
yarn一直在跑一个用户为dr.who的application
查看>>
linux中shell变量$#,$@,$0,$1,$2的含义解释
查看>>
测试调用接口
查看>>
CPU 实模式 保护模式 和虚拟8086模式
查看>>
Selenium获取input值的两种方法:WebElement.getAttribute("value")和WebElement.getText()
查看>>
南邮CTF--md5_碰撞
查看>>
mysqldump默认参数add-drop-table
查看>>
python第十一周:RabbitMQ、Redis
查看>>
构造函数
查看>>
ARCGIS中怎么去除重复的面?(转)
查看>>
[转载]你知道我今天为什么来公司上班吗?
查看>>
jenkins 和 git 的每日构建
查看>>
《Java技术》第九次作业
查看>>
Python私有属性set和get方法2
查看>>
【清北学堂2018-刷题冲刺】Contest 5
查看>>
BZOJ3218 UOJ#77 A+B Problem(最小割+主席树)
查看>>
ffmpeg-201612[01,08,10,17,21,27,30]-bin.7z
查看>>
【IntellJ IDEA】idea忽略隐藏文件、文件夹的设置操作
查看>>
[转]TextView显示系统时间(秒针变化)
查看>>