您的位置:首页 > 移动开发 > IOS开发

iOS异步图片加载优化与常用开源库分析

2016-06-02 09:57 357 查看

网络图片显示大体步骤:

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来做一些主线程与子线程的切换。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: