目录
一、SDWebImage安装集成
(1)安装
(2)集成
二、SDWebImage原理说明
(1)缓存的概念(计算机的存储方式、缓存的种类以及区别)
(2)一级缓存和二级缓存的交互
(3)二级缓存概念和作用
(4)小结-->SDWebImage的缓存机制原理
三、SDWebImage源码实现步骤
(1)常见的四种加载方式
(2)加载步骤
(3)清理缓存
(4)系统默认清理缓存
(5)小节
四、总结
正文
一、SDWebImage安装集成
安装方式两种
1、直接cocoapods安装 在文件夹生成的podfile文件中添加pod 'SDWebImage' 终端cd + 文件位置 然后pod install即可
2、直接下载SDWebImage,然后将文件夹拖拽到本地项目即可.github托管地址https://github.com/rs/SDWebImage
集成
只需要导入头文件#import "UIImageView+WebCache.h"即可
二、SDWebImage原理说明
1、缓存的概念
什么叫缓存?
1、缓存是CPU的一部分,他存在于CPU中,CPU存取数据的速度非常快,一秒钟能够存取,处理十亿条指令和数据,而内存就很慢了,快的内存也就达到几十兆,两者速度差异很大。内存中被CPU访问最频繁的数据和指令被赋值入CPU中的缓存,这样需要缓存数据的时候就不用下载,直接取就可以了。
2、缓存只是内存中少部分数据的复制品,所以CPU在寻找数据的时候也会出现找不到的情况(因为这个数据没有从内存复制到缓存中去),这样系统的速度就慢下来了,不过CPU会把这些数据复制到缓存中去,以便下次不再从内存中取数据了。
计算机存在的存储方式都有哪种?(RAM和ROM)
RAM-RamdomAccessMemory易挥发性随机存取存储器,高速存取,读写时间相等,且与地址无关,如计算机内存等。
ROM-Read Only Memory只读存储器。断电后信息不丢失,如计算机启动用的BIOS芯片。存取速度很低,(较RAM而言)且不能改写。由于不能改写信息,不能升级,现已很少使用。
ROM和RAM是计算机内存储器的两种型号,ROM表示的是只读存储器,即:它只能读出信息,不能写入信息,计算机关闭电源后其内的信息仍旧保存,一般用它存储固定的系统软件和字库等。RAM表示的是读写存储器,可其中的任一存储单元进行读或写操作,计算机关闭电源后其内的信息将不在保存,再次开机需要重新装入,通常用来存放操作系统,各种正在运行的软件、输入和输出数据、中间结果及与外存交换信息等,我们常说的内存主要是指RAM。
缓存的种类都有哪种?区别是什么?(SRAM和DRAM)
1、在RAM的概念当中也存在静态缓存(SRAM)和动态缓存(DRAM)
2、静态缓存的速度远远>动态缓存的速度
3、静态缓存的体积=6*动态缓存的体积(两者体积6倍关系)
4、静态缓存的价格=4*动态缓存的价格(两者价格4倍关系)
现在常见提高缓存速度的方式是什么?
增加二级缓存(二级缓存就是增加动态的RAM)——这里有人会问了,为什么不增加静态缓存呢(上面两者的对比已经列出,更何况缓存的存在就是为了减缓CPU访问内存的压力,所以无论是动态缓存还是静态缓存的增加都是为了缓解CPU的压力)
(2)一级缓存和二级缓存的交互、那么一级缓存和二级缓存的交互是怎样实现的呢?
1、存在都是为了减少高速CPU对慢速内存的访问
2、通常CPU找数据或指令的顺序是:先到一级缓存中找,找不到再到二级缓存中找,如果还找不到就只有到内存中找了
(3)二级缓存概念和作用
二级缓存到底是什么?它是干什么用的?
二级缓存又叫L2 CACHE,它是处理器内部的一些缓冲存储器,其作用跟内存一样。 它是怎么出现的呢?
要上溯到上个世纪80年代,由于处理器的运行速度越来越快,慢慢地,处理器需要从内存中读取数据的速度需求就越来越高了。
然而内存的速度提升速度却很缓慢,而能高速读写数据的内存价格又非常高昂,不能大量采用。
从性能价格比的角度出发,英特尔等处理器设计生产公司想到一个办法,就是用少量的高速内存和大量的低速内存结合使用,共同为处理器提供数据。
这样就兼顾了性能和使用成本的最优。而那些高速的内存因为是处于CPU和内存之间的位置,又是临时存放数据的地方,所以就叫做缓冲存储器了,简称“缓存”。
它的作用就像仓库中临时堆放货物的地方一样,货物从运输车辆上放下时临时堆放在缓存区中,然后再搬到内部存储区中长时间存放。货物在这段区域中存放的时间很短,就是一个临时货场。
最初缓存只有一级,后来处理器速度又提升了,一级缓存不够用了,于是就添加了二级缓存。
二级缓存是比一级缓存速度更慢,容量更大的内存,主要就是做一级缓存和内存之间数据临时交换的地方用。现在,为了适应速度更快的处理器P4EE,已经出现了三级缓存了,它的容量更大,速度相对二级缓存也要慢一些,但是比内存可快多了。
缓存的出现使得CPU处理器的运行效率得到了大幅度的提升,这个区域中存放的都是CPU频繁要使用的数据,所以缓存越大处理器效率就越高,同时由于缓存的物理结构比内存复杂很多,所以其成本也很高。
4、小结--> SDWebImage的缓存机制
typedef NS_ENUM(NSInteger, SDImageCacheType) {
/**
* The image wasn't available the SDWebImage caches, but was downloaded from the web.(这张图片没有提供SDWebImage缓存,但从网上下载。)
*/
SDImageCacheTypeNone,
/**
* The image was obtained from the disk cache.(图像是从磁盘缓存中获得的。)
*/
SDImageCacheTypeDisk,
/**
* The image was obtained from the memory cache.(图像是从内存缓存中获得的。)
*/
SDImageCacheTypeMemory
};
SDWebImage底层实现缓存机制,主要由三块组成
1、网络下载获取(当缓存中寻找不到的情况下->下载完之后会自动存储到好磁盘缓存中)
2、磁盘缓存获取
3、内存缓存获取
这里 SDImageCache维护一个内存缓存和一个可选的磁盘缓存。磁盘缓存写操作是异步执行的,所以它不会给UI增加不必要的延迟
原理如下------
1)当我门需要获取网络图片的时候,我们首先需要的便是URL,获得URL后我们SDWebImage实现的并不是直接去请求网路,而是检查图片缓存中有没有和URl相关的图片,如果有则直接返回image,如果没有则进行下一步。
2)当图片缓存中没有图片时,SDWebImage依旧不会直从网络上获取,而是检查沙盒中是否存在图片,如果存在,则把沙盒中对应的图片存进image缓存中,然后按着第一步的判断进行。
3)如果沙盒中也不存在,则显示占位图,然后根据图片的下载队列缓存判断是否正在下载,如果下载则等待,避免二次下载。如果不存则创建下载队列,下载完毕后将下载操作从队列中清除,并且将image存入图片缓存中。
4)刷新UI(当然根据实际情况操作)将image存入沙盒缓存。
三、SDWebImage源码实现步骤
常见的四种加载方式
1、无占位图直接加载(如果缓存中存在改图片则直接获取无需重新下载增加磁盘缓存)
- (void)sd_setImageWithURL:(nullable NSURL *)url {
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
}
2、有占位图直接加载(如果URL加载不到则展示占位图,如果缓存中存在改图片则直接获取无需重新下载增加磁盘缓存)
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder {
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
}
3、有占位图直接加载,并且实现图片加载完之后的Block可以继续完成下一步操作(如果URL加载不到则展示占位图,如果缓存中存在改图片则直接获取无需重新下载增加磁盘缓存)
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
}
4、可以选择options的形式加载图片,(如果URL加载不到则展示占位图,如果缓存中存在改图片则直接获取无需重新下载增加磁盘缓存)
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
}
/*使用可更换optionsType的加载方式
-------------Options 枚举下的加载方式-----------
SDWebImageRetryFailed 默认情况下,当URL无法下载时,URL就会被列入黑名单,这样库就不会继续尝试了。此标记禁用此黑名单。
SDWebImageLowPriority 默认情况下,图像下载是在UI交互过程中启动的,这标志禁用该特性,导致在UIScrollView减速方面延迟下载。
SDWebImageCacheMemoryOnly 此标记禁用磁盘缓存
SDWebImageProgressiveDownload 此标志可以进行渐进式下载,在下载过程中,图像会逐步显示,就像浏览器所做的那样。默认情况下,图像只显示一次完全下载。
SDWebImageRefreshCached 即使缓存了映像,也要尊重HTTP响应缓存控制,并在需要的情况下从远程位置刷新映像。磁盘缓存将由NSURLCache来处理,而不是使用SDWebImage,这会导致轻微的性能下降。这个选项有助于处理在同一个请求URL后面更改的图像,例如Facebook图形api概要图。如果刷新了缓存的图像,那么完成块就会被缓存的图像和最后的图像再次调用一次。只有当你不能用嵌入的缓存破坏参数使你的url静态时,才使用这个标志。
SDWebImageContinueInBackground 在iOS 4+中,如果应用程序进入后台,可以继续下载图片。这是通过请求系统在后台获得额外的时间来完成请求完成的。如果后台任务过期,操作将被取消。
SDWebImageHandleCookies 通过设置NSMutableURLRequest来处理存储在NSHTTPCookieStore中的cookie。HTTPShouldHandleCookies =是的;
SDWebImageAllowInvalidSSLCertificates 启用不受信任的SSL证书。用于测试目的。在生产中使用谨慎。
SDWebImageHighPriority 默认情况下,图像按顺序装载在队列中。这个标志把它们移到队列的前面。
SDWebImageDelayPlaceholder 默认情况下,在图像加载时加载占位符图像。此标志将延迟加载占位符图像,直到图像完成加载。
SDWebImageTransformAnimatedImage 我们通常不会在动画图像上调用transformdownloade昏暗委托方法,因为大多数转换代码会把它搞砸。无论如何,使用这个标志来转换它们。* /
SDWebImageAvoidAutoSetImage 默认情况下,图像会在下载后添加到imageView中。但是在某些情况下,我们想要在设置图像之前有手(例如,应用一个过滤器或将它添加到交叉衰减动画中)使用这个标记如果你想在成功完成时手工设置图像
SDWebImageScaleDownLargeImages 默认情况下,图像会被解码,以尊重它们原来的大小。在iOS上,这一标志将把图像缩小到与设备受限内存兼容的大小。*如果“SDWebImageProgressiveDownload”标志设置禁用缩减。
*/
以上四个常用方法,点击进去查看内部实现代码时,你会发现所有方法都指向------>
源码注释解释的含义是
用url、占位符和自定义选项设置imageView图像。下载是异步的和缓存的。
@param url是图像的url。
@param占位符将首先设置的图像,直到图像请求完成。
@param选择在下载图像时使用的选项。
@参见SDWebImageOptions用于可能的值。
@param progressBlock在下载@note时,在后台队列
@param completedBlock的后台进程中执行进程块,该块是在操作完成时被调用的。这个块没有返回值,并将所请求的UIImage作为第一个参数。在出现错误时,图像参数为nil,第二个参数可能包含一个NSError。第三个参数是一个布尔值,指示是否从本地缓存或网络检索图像。第四个参数是原始图像url。
下面是图解(上面展示了每句话的备注)
1、设置展位图,并且取消当前下载任务
2、创建一个新的下载操作
3、下载操作代码(判断流是否存在,如果不存在则将其存在失效列表中,防止重复下载无效流)-----在这里他对NSString和NSURL的转换做了判断。原因是(非常常见的错误是使用NSString对象而不是NSURL发送URL。出于某种奇怪的原因,Xcode不会对这种类型的不匹配发出任何警告。在这里,我们通过允许url作为NSString传递来确保这个错误。)括号当中是文档给出的解释,所以这里做了强制转换。
4、利用唯一生成的key,到缓存--->内存---->磁盘中分别寻找。
5、寻找的顺序 缓存---->磁盘---->在没有就下载
下载流程之后就是清理缓存(种类) 1、清理所有内存缓存镜像 2、清理所有磁盘缓存镜像3、清理过期的缓存映像从磁盘中删除
/*
异步清除所有磁盘缓存映像。非阻塞方法-立即返回。@param完成一个应该在缓存过期后执行的块(可选)
注意:这里要注意[[SDImageCache sharedImageCache] clearDisk];方法会报错,下面clearDiskOnCompletion的方法会替代上面的方法
*/
[[SDImageCache sharedImageCache] clearDiskOnCompletion:^{
}];
/*
Clear all memory cached images --->清除所有缓存镜像
*/
[[SDImageCache sharedImageCache] clearMemory];
/*
异步将所有过期的缓存映像从磁盘中删除。非阻塞方法-立即返回。@param completionBlock在缓存过期后执行(可选)--->故名思义他是不能删除你当前缓存的大小的
*/
[[SDImageCache sharedImageCache] deleteOldFilesWithCompletionBlock:^{
}];
当然清理的方式不仅仅手动操作. ------> SDWebImage自动也会清理内存,默认周期为一周
小节
1、如果在加载图片的过程中出现程序报错(App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.)
你需要操作如下--------
(1)、在Info.plist中添加 NSAppTransportSecurity 类型 Dictionary ;
(2)、在 NSAppTransportSecurity 下添加 NSAllowsArbitraryLoads 类型Boolean ,值设为 YES;
2、SDWebImage通过唯一镜像的方式查找图片的顺序如下---
内存缓存 ------->磁盘缓存 ------>通过URL下载图片并且存储到磁盘当中。
小结-->
1.setImageWithURL:placeholderImage:options:
会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始 处 图 。
2.进SDWebImageManagerdownloadWithURL: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作为一个优秀的图片加载框架
1、大量的block回调,可能看起来并没有那么直观
2、都采用异步的操作方式
3、报漏方法简单易懂(开文中说的四种常见展示图片的方法)