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

SDWebImage浅析的更多相关文章
- IOS 网络浅析-(十三 SDWebImage 实用技巧)
IOS 网络浅析-(十三 SDWebImage 实用技巧) 首先让我描述一下为了什么而产生的实用技巧.(在TableView.CollectionView中)当用户所处环境WiFi网速不够快(不能立即 ...
- 浅析SDWebImage
浅析SDWebImage 在日常的开发过程中,如果去优雅的访问网络的图片并去管理每个工程必须要面对的问题,如果想要在工程里面提供易用.简洁.方便管理的解决方案还是很有挑战的,毕竟还要兼顾图片文件的缓存 ...
- IOS 网络浅析-(六 网络图片获取之三方SDWebImage)
网络图片获取是大多数app所能用到的,由于实际app开发中原生api很少用到,在这里就先不介绍了,以后有时间会给大家介绍.这篇文章会给大家介绍一个三方-SDWebImage.SDWebImage 是一 ...
- SDWebImage源码刨根问底
前言: SDWebImage是iOS中一款处理图片的框架, 使用它提供的方法, 一句话就能让UIImageView,自动去加载并显示网络图片,将图片缓存到内存或磁盘缓存,正好有阅读开源项目的计划,于是 ...
- SDWebImage源码解读之SDWebImageDownloaderOperation
第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
- SQL Server on Linux 理由浅析
SQL Server on Linux 理由浅析 今天的爆炸性新闻<SQL Server on Linux>基本上在各大科技媒体上刷屏了 大家看到这个新闻都觉得非常震精,而美股,今天微软开 ...
- 【深入浅出jQuery】源码浅析--整体架构
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- 高性能IO模型浅析
高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking ...
- netty5 HTTP协议栈浅析与实践
一.说在前面的话 前段时间,工作上需要做一个针对视频质量的统计分析系统,各端(PC端.移动端和 WEB端)将视频质量数据放在一个 HTTP 请求中上报到服务器,服务器对数据进行解析.分拣后从不同的 ...
随机推荐
- jpeg错误打印结构
struct jpeg_error_mgr { /* Error exit handler: does not return to caller */ JMETHOD(void, error_exit ...
- iOS开发密码输入数字和字母混合
#import "TestInPut.h" @implementation TestInPut +(BOOL)judgePassWordLegal:(NSString *)pass ...
- strust2 和 hibernate的整合------登录的实现
初步认识了struts2,并与hibernate进行整合,完成了一个登录的案例,下面贴源码 1.实体类User public class User { private Integer id; priv ...
- 查看文件内容- 删除某个运行程序的所有进程-nohup后台执行程序
1 查看文件内容: tail -f test.txt 2 查看端口 netstat nlp 3 删除某个运行程序的所有进程 ps -ef|grep translateService.py|grep - ...
- libubox组件(3)——uloop
一:uloop概述 uloop有三个功能: 文件描述符触发事件的监控, timeout定时器处理, 当前进程的子进程的维护 二: uloop的整体框架 1: /** 2: * 初始化事件循环 3: ...
- 配置LANMP环境(3)-- 安装anmp前准备与实用软件安装
一.安装配置vim 1.安装 yum -y install vim* 2.创建文件夹 mkdir -p /etc/vim/ 3.配置 vim ~/.vimrc "插入模式时 光标的上下左右 ...
- 第一百九十六节,jQuery EasyUI,Tooltip(提示框)组件
jQuery EasyUI,Tooltip(提示框)组件 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 Tooltip(提示框)组件的使用方法, ...
- Eclipse 浏览(Navigate)菜单
浏览 Eclipse 工作空间 浏览(Navigate)菜单提供了多个菜单可以让你快速定位到指定资源. 上图中 Open Type, Open Type in Hierarchy 和 Open Res ...
- 打印99乘法表-python
题目:如何打印出阶梯状的99乘法表? 题解: #coding:utf-8def multiplication_tables(num):#for i in range(1,10): for j in r ...
- 第二章----python函数
第一节:调用函数 1.函数是什么? 函数是组织好的,可以重复利用的. 2.为什么要用到函数? 提高应用的模块性,提高重复利用率.指的是:多个文件中可能都要用到该函数,直接拿来调用就行,不用在重复写一个 ...