SDWebImage浅析

第一部分

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下的资源解压,然后画在另外一张图片上,这样这张新图片就不再需要重复解压了。

这种做法是典型的空间换时间的做法。

第二部分

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 可以预先下载图片,方便后续使用。

时间: 2024-11-05 18:00:33

SDWebImage浅析的相关文章

linux进程调度浅析

操作系统要实现多进程,进程调度必不可少. 有人说,进程调度是操作系统中最为重要的一个部分.我觉得这种说法说得太绝对了一点,就像很多人动辄就说"某某函数比某某函数效率高XX倍"一样,脱离了实际环境,这些结论是比较片面的. 而进程调度究竟有多重要呢? 首先,我们需要明确一点:进程调度是对TASK_RUNNING状态的进程进行调度(参见<linux进程状态浅析>).如果进程不可执行(正在睡眠或其他),那么它跟进程调度没多大关系. 所以,如果你的系统负载非常低,盼星星盼月亮才出现一

模仿SDWebImage实现异步加载图片

模仿SDWebImage实现异步加载图片 SDWebImage想必大家都不陌生吧,要实现它的图片异步加载功能这个还是很简单的. 注意:此处我只实现了异步加载图片,并没有将文件缓存到本地的打算哦:) 源码: UIImageView+YXImageView.h // // UIImageView+YXImageView.h // PicDemo // // Copyright (c) 2014年 Y.X. All rights reserved. // #import <UIKit/UIKit.h>

浅析win7下IE8主页被篡改的修复过程

浅析win7下IE8主页被篡改的修复过程 很多网友都有这个烦恼,在打开住页面时,页面就会开始变化,不再是自己熟悉的版本主页,所以要解决IE8被篡改的问题,我们就要充分的挖掘Windows7的系统"潜能",提升让IE8自我保护能力.现在我们深度xp系统下载一起来看看要怎么解决吧! 运行注册表编辑器,一次展开到HKEY_CURRENT_USER/Software/Policies/Microsoft,在此分支下新建一个名为"ControlPanel"的项,(具体操作为:

linux pi_futex浅析

Priority Inheritance,优先级继承,是解决优先级反转的一种办法. 一个经典的例子:A/B/C三个实时进程,优先级A>B>C.C持有a锁,而A等待a锁被挂起.原本C释放a锁之后,A进程就可以继续执行的,但是偏偏有个比C优先级高的B进程存在,导致C得不到运行,也就没法释放a锁,从而导致A进程一直挂起.从整体上看,进程B虽然比A优先级低,但它却成功的抢占掉了A.这就是所谓的优先级反转. 一种解决办法是优先级继承,C在持有a锁期间临时继承等待者A的优先级,那么B进程就无法从中捣乱了.

linux内核SMP负载均衡浅析

需求 在<linux进程调度浅析>一文中提到,在SMP(对称多处理器)环境下,每个CPU对应一个run_queue(可执行队列).如果一个进程处于TASK_RUNNING状态(可执行状态),则它会被加入到其中一个run_queue(且同一时刻仅会被加入到一个run_queue),以便让调度程序安排它在这个run_queue对应的CPU上面运行. 一个CPU对应一个run_queue这样的设计,其好处是: 1.一个持续处于TASK_RUNNING状态的进程总是趋于在同一个CPU上面运行(其间,这

linux文件读写浅析

在<linux内核虚拟文件系统浅析>这篇文章中,我们看到文件是如何被打开.文件的读写是如何被触发的. 对一个已打开的文件fd进行read/write系统调用时,内核中该文件所对应的file结构的f_op->read/f_op->write被调用. 本文将顺着这条路走下去,大致看看普通磁盘文件的读写是怎样实现的. linux内核响应一个块设备文件读写的层次结构如图(摘自ULK3): 1.VFS,虚拟文件系统. 之前我们已经看到f_op->read/f_op->write如

linux进程状态浅析

众所周知,现在的分时操作系统能够在一个CPU上运行多个程序,让这些程序表面上看起来是在同时运行的.linux就是这样的一个操作系统. 在linux系统中,每个被运行的程序实例对应一个或多个进程.linux内核需要对这些进程进行管理,以使它们在系统中"同时"运行.linux内核对进程的这种管理分两个方面:进程状态管理,和进程调度.本文主要介绍进程状态管理,进程调度见<linux进程调度浅析>. 进程状态 在linux下,通过ps命令我们能够查看到系统中存在的进程,以及它们的状

linux网络报文接收发送浅析

对于linux内核来说,网络报文由网络设备来进行接收.设备驱动程序从网络设备中读取报文,通过内核提供的网络接口函数,将报文传递到内核中的网络协议栈.报文经过协议栈的处理,或转发.或丢弃.或被传送给某个进程. 网络报文的发送与之相反,进程通过系统调用将数据送入网络协议栈,或者由网络协议栈自己发起报文的发送,然后协议栈通过调用网络接口函数来调度驱动程序,使其将报文传送给网络设备,从而发送出去. 本文讨论的是网络接口层,它是网络设备驱动程序与网络协议栈交互的纽带.见下图中红色部分的netif. 报文的

ios-使用SDWebImage时想要更改缓存

问题描述 使用SDWebImage时想要更改缓存 在开发过程中遇到的一个问题,SDWebImage的缓存机制是根据URL来的,所以当后台在URL不变的情况下更改了图片,客户端使用的仍然是未更改前的图片,只有用户清除了缓存后再进入应用才能看到这张新图片,那么问题来了,如果是诸如显示头像这种有可能会经常更换的图片,不得不进行缓存更改了,SDWebImage的sd_setImageWithURL方法中可以携带一个option参数,这个参数默认是0,如果使用SDWebImageRefreshCached