对于ASIHttp请求和AFNetworking请求都有关于图片缓存机制的使用,但是相对于专注运用在图片使用的SDWebimage来说,又有不一样的使用效果,最主要的体现在缓存数据的转换。

SDWebImage是一个很厉害的图片缓存的框架。以前是ASIHttp+AsyncImage,后来使用AFNetworking集成的UIImageView+AFNetworking.h,但后者对于图片的缓存实际应用的是NSURLCache自带的cache机制。而NSURLCache每次都要把缓存的raw
 data 再转化为UIImage,就带来了数据处理和内存方面的更多操作。具体的比较在这里

SDWebImage提供了如下三个category来进行缓存。

这个类库提供一个UIImageView类别以支持加载来自网络的远程图片。具有缓存管理、异步下载、同一个URL下载次数控制和优化等特征。

SDWebImage 加载图片的流程

  1. 入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片。
  2. 进入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交给 SDImageCache 从缓存查找图片是否已经下载 queryDiskCacheForKey:delegate:userInfo:.
  3. 先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。
  4. SDWebImageManagerDelegate 回调 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示图片。
  5. 如果内存缓存中没有,生成 NSInvocationOperation 添加到队列开始从硬盘查找图片是否已经缓存。
  6. 根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 notifyDelegate:。
  7. 如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:。进而回调展示图片。
  8. 如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调 imageCache:didNotFindImageForKey:userInfo:。
  9. 共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。
  10. 图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。
  11. connection:didReceiveData: 中利用 ImageIO 做了按图片下载进度加载效果。
  12. connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。
  13. 图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。
  14. 在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给 SDWebImageDownloader。
  15. imageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。
  16. 通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。
  17. 将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。写文件到硬盘也在以单独 NSInvocationOperation 完成,避免拖慢主线程。
  18. SDImageCache 在初始化的时候会注册一些消息通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。
  19. SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。
  20. SDWebImagePrefetcher 可以预先下载图片,方便后续使用

SDWebImage库的作用

通过对UIImageView的类别扩展来实现异步加载替换图片的工作。

主要用到的对象:

1、UIImageView (WebCache)类别,入口封装,实现读取图片完成后的回调

2、SDWebImageManager,对图片进行管理的中转站,记录那些图片正在读取。

向下层读取Cache(调用SDImageCache),或者向网络读取对象(调用SDWebImageDownloader) 。

实现SDImageCache和SDWebImageDownloader的回调。

3、SDImageCache,根据URL的MD5摘要对图片进行存储和读取(实现存在内存中或者存在硬盘上两种实现)

实现图片和内存清理工作。

4、SDWebImageDownloader,根据URL向网络读取数据(实现部分读取和全部读取后再通知回调两种方式)

其他类:

SDWebImageDecoder,异步对图像进行了一次解压⋯⋯

相关问题:

1、SDImageCache是怎么做数据管理的?

SDImageCache分两个部分,一个是内存层面的,一个是硬盘层面的。

内存层面的相当是个缓存器,以Key-Value的形式存储图片。当内存不够的时候会清除所有缓存图片。

用搜索文件系统的方式做管理,文件替换方式是以时间为单位,剔除时间大于一周的图片文件。

当SDWebImageManager向SDImageCache要资源时,先搜索内存层面的数据,如果有直接返回,没有的话去访问磁盘,将图片从磁盘读取出来,然后做Decoder,将图片对象放到内存层面做备份,再返回调用层。

2、为啥必须做Decoder?

通过这个博客:http://www.cocoanetics.com/2011/10/avoiding-image-decompression-sickness/

现在明白了,由于UIImage的imageWithData函数是每次画图的时候才将Data解压成ARGB的图像,

所以在每次画图的时候,会有一个解压操作,这样效率很低,但是只有瞬时的内存需求。

为了提高效率通过SDWebImageDecoder将包装在Data下的资源解压,然后画在另外一张图片上,这样这张新图片就不再需要重复解压了。



以最为常用的UIImageView为例:

  1. UIImageView+WebCache:  setImageWithURL:placeholderImage:options: 先显示 placeholderImage
    ,同时由SDWebImageManager 根据 URL 来在本地查找图片。
  2. SDWebImageManager: downloadWithURL:delegate:options:userInfo: SDWebImageManager是将UIImageView+WebCache同SDImageCache链接起来的类, SDImageCache: queryDiskCacheForKey:delegate:userInfo:用来从缓存根据CacheKey查找图片是否已经在缓存中
  3. 如果内存中已经有图片缓存, SDWebImageManager会回调SDImageCacheDelegate : imageCache:didFindImage:forKey:userInfo:
  4. 而 UIImageView+WebCache 则回调SDWebImageManagerDelegate:  webImageManager:didFinishWithImage:来显示图片。
  5. 如果内存中没有图片缓存,那么生成 NSInvocationOperation 添加到队列,从硬盘查找图片是否已被下载缓存。
  6. 根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 notifyDelegate:
  7. 如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:。进而回调展示图片。
  8. 如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调 imageCache:didNotFindImageForKey:userInfo:
  9. 共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。
  10. 图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。
  11. connection:didReceiveData: 中利用 ImageIO 做了按图片下载进度加载效果。
  12. connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。
  13. 图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。
  14. 在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给
    SDWebImageDownloader。
  15. imageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。
  16. 通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。
  17. 将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。
  18. 写文件到硬盘在单独 NSInvocationOperation 中完成,避免拖慢主线程。
  19. 如果是在iOS上运行,SDImageCache 在初始化的时候会注册notification 到 UIApplicationDidReceiveMemoryWarningNotification 以及  UIApplicationWillTerminateNotification,在内存警告的时候清理内存图片缓存,应用结束的时候清理过期图片。
  20. SDWebImagePrefetcher 可以预先下载图片,方便后续使用。

SDWebimage的原理和使用机制的更多相关文章

  1. SDWebImage的原理 和 实现机制 --- tableView 滑动卡的问题

    一.原理 1)当我门需要获取网络图片的时候,我们首先需要的便是URl没有URl什么都没有,获得URL后我们SDWebImage实现的并不是直接去请求网路,而是检查图片缓存中有没有和URl相关的图片,如 ...

  2. 追踪app崩溃率、事件响应链、Run Loop、线程和进程、数据表的优化、动画库、Restful架构、SDWebImage的原理

    1.如何追踪app崩溃率,如何解决线上闪退 当 iOS设备上的App应用闪退时,操作系统会生成一个crash日志,保存在设备上.crash日志上有很多有用的信息,比如每个正在执行线程的完整堆栈 跟踪信 ...

  3. typecho流程原理和插件机制浅析(第二弹)

    typecho流程原理和插件机制浅析(第二弹) 兜兜 393 2014年04月02日 发布 推荐 1 推荐 收藏 14 收藏,3.7k 浏览 上一次说了 Typecho 大致的流程,今天简单说一下插件 ...

  4. typecho流程原理和插件机制浅析(第一弹)

    typecho流程原理和插件机制浅析(第一弹) 兜兜 393 2014年03月28日 发布 推荐 5 推荐 收藏 24 收藏,3.5k 浏览 虽然新版本0.9在多次跳票后终于发布了,在漫长的等待里始终 ...

  5. Struts2漏洞利用原理及OGNL机制

    Struts2漏洞利用原理及OGNL机制研究   概述 在MVC开发框架中,数据会在MVC各个模块中进行流转.而这种流转,也就会面临一些困境,就是由于数据在不同MVC层次中表现出不同的形式和状态而造成 ...

  6. 深入理解Redis主键失效原理及实现机制(转)

    原文:深入理解Redis主键失效原理及实现机制 作为一种定期清理无效数据的重要机制,主键失效存在于大多数缓存系统中,Redis 也不例外.在 Redis 提供的诸多命令中,EXPIRE.EXPIREA ...

  7. 李洪强iOS开发之RunLoop的原理和核心机制

    李洪强iOS开发之RunLoop的原理和核心机制 搞iOS之后一直没有深入研究过RunLoop,非常的惭愧.刚好前一阵子负责性能优化项目,需要利用RunLoop做性能优化和性能检测,趁着这个机会深入研 ...

  8. 《【面试突击】— Redis篇》-- Redis哨兵原理及持久化机制

    能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis哨兵原理及持久化机制 在这个系列里, ...

  9. [面向对象之继承应用(在子类派生重用父类功能(super),继承实现原理(继承顺序、菱形问题、继承原理、Mixins机制),组合]

    [面向对象之继承应用(在子类派生重用父类功能(super),继承实现原理(继承顺序.菱形问题.继承原理.Mixins机制),组合] 继承应用 类与类之间的继承指的是什么'是'什么的关系(比如人类,猪类 ...

随机推荐

  1. 2.5、Android Studio添加多适配的向量图片

    Android Studio包含一个Vector Asset Studio的工具,可以帮助你添加Material图标和导入SVG(Scalable Vector Graphic)文件到你的项目中作为向 ...

  2. 【移动开发】ViewPager缓存机制

    1.    实现ViewPager的页面懒加载:在某些情况下,例如使用ViewPager查看多张大图,此时多张图片不能一次性载入,只有在浏览该页面时才载入(或者预先载入下一页面)页面的具体内容.2. ...

  3. sublime text3空格和tab的显示

    最近在使用sublime text3修改shell文件时,明明看着相同的文件,对比却说不一样.最后发现是空格和tab惹的祸. 1.显示空格和tab: 在Preferences→Key Bindings ...

  4. 显示图像的SIFT flow描述子

    close all; % 模拟figure 5 im = zeros(401,401,3); im(:,:,:) = 0; im(2:200, 2:200, 2) = 255; im(202:400, ...

  5. 安卓AsyncTack详解

    我们知道安卓中的UI线程不是线程安全的,即不能在UI线程中进行耗时操作,所以我们通常的做法是开启一个子线程来进行耗时操作,然后将处理后的结果运用Handler机制传递给UI线程,在UI线程中根据处理后 ...

  6. Unable to instantiate Action, MenuAction, defined for 'QueryMenuAll' in namespace '/'MenuAction

    我刚好也遇到这样的情况,发现是自己的配置文件里写错了,spring里的id属性值要对应struts里class属性值.

  7. hadoop cdh5的pig隐式转化(int到betyarray)不行了

    cdh3上,pig支持int到chararray的隐式转化,但到cdh5不行. pig code is as follows: %default Cleaned_Log /user/usergroup ...

  8. Oracle EBS R12文件系统结构(学习汇总网上资料)

    Oracle EBS R12在服务器端文件结构如下: 顶层目录下面分为 1)inst --–跟ebs整个实例(instance)相关的配置信息以及其他信息 2)  db   ---主要存储DB层的信息 ...

  9. 如何在Cocos2D 1.0 中掩饰一个精灵(六)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 掩饰一个精灵:实现代码 打开HelloWorldLayer.m并 ...

  10. Oracle WorkFlow(工作流)(二)

    2.4消息(Message) 消息主要是为通知服务的,可以把消息当作通知的内容和类型.消息也属于一个单据类型,通知只能和同一个单据类型里的消息相关联. 每个消息可以有一个或多个属性和自己相联系,消息的 ...