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 请求中上报到服务器,服务器对数据进行解析.分拣后从不同的 ...
随机推荐
- VS2017调试MVC程序,中文输入法下浏览器闪退,程序调试终止
工具->选项-> 项目和解决方案->Web项目->浏览器窗口关闭时停止调试器(s) 复选√ 去掉即可,
- C++语言基础(7)-inline内联函数
函数调用是有时间和空间开销的.程序在执行一个函数之前需要做一些准备工作,要将实参.局部变量.返回地址以及若干寄存器都压入栈中,然后才能执行函数体中的代码:函数体中的代码执行完毕后还要清理现场,将之前压 ...
- Django数据库表的关联问题
Django模型中,比较难以理解的要数表和表之间相关联的部分,下面主要说说外键-ForeignKey和ManyToManyField2个字段类型. 我们知道ForeignKey说的是“一对多”,那么问 ...
- centos7系统备份与还原
1. 前言 在使用Ubuntu之前,相信很多人都有过使用Windows系统的经历.如果你备份过Windows系统,那么你一定记忆犹新:首先需要找到一个备份工具(通常都是私有软件),然后重启电脑进入备份 ...
- oracle 插入记录,字段自动获取当前系统时间(YYYY-MM-DD HH24:MI:SS)
需求: 插入一条记录,要求自动获取当前日期,并且格式为(YYYY-MM-DD HH24:MI:SS) sql语句: insert into SY_COMM_CONFIG(CONF_ID, S_MTIM ...
- linux命名空间详解_转
转自: Linux的命名空间详解--Linux进程的管理与调度(二) Linux Namespaces机制提供一种资源隔离方案. PID,IPC,Network等系统资源不再是全局性的,而是属于特定的 ...
- memcached 经常使用命令最全总结大全
1.首先.总结一下memcached的一些基本设置 -p 监听的port -l 连接的IP地址, 默认是本机 -d start 启动memcached服务 -d restart 重起memcached ...
- 如何创建Windows定时任务
我们经常使用电脑,有没有那么一个瞬间想着要是电脑可以每隔一段时间,自动处理一件事情就好了呢? 其实Windows还真有这样的功能,很多软件检测更新就是通过这个方法实现的. 这次我们来做一个简易的喝水提 ...
- 012android初级篇之Handler机制
设计Handler类的目的 Handler类被用来注册到一个线程中,这样可以提供一个简单的通信渠道,用来发送数据到这个线程. 可作为UI线程与后台线程交互的几种方法之一. 具体用途 消息的分发和处理, ...
- CentOS 6.5 安装Gitlab 7.12.2
官网环境要求 参见:https://github.com/gitlabhq/gitlabhq GitLab is a Ruby on Rails application that runs on th ...