zoukankan      html  css  js  c++  java
  • iOS异步图片加载优化与常用开源库分析

    网络图片显示大体步骤:

    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来做一些主线程与子线程的切换。

  • 相关阅读:
    Delphi中创建一个可以改变大小的无边框窗口
    Delphi中让窗口关闭按钮无效的6种方法
    把人笑抽筋的签名
    Delphi中判断窗体最大化和最小化事件
    Delphi中窗体的帮助按钮上执行一个自定义的动作
    无法查询部门收支分析表
    Delphi中去掉限制窗体最小尺寸的Windows约束
    Delphi中在窗体标题栏画自定义文字
    调拨单等单据定位功能没有过滤条件
    Form中对象的引用
  • 原文地址:https://www.cnblogs.com/fengmin/p/5551986.html
Copyright © 2011-2022 走看看