SDWebImage源码解析

SDWebImage是我们非常常用的一个关于图片下载缓存的框架。下面的源码分析是基于版本3.8。下面是gitHub上的介绍:

主要作用:

1、为UIiamgeView,UIbutton  等控件加载网络图片,并且进行缓存管理

2、一个异步图片下载工具

3、一个异步的内存和硬盘的图片缓存,提供自动的缓存处理

4、异步的图片解码

5、保证相同的URL不会多次下载

6、保证不合法的URL不会被多次下载

7、保证主线程不会被阻塞

8、自定义

9、使用GCD 和 ARC

为什么使用SDWebImage而不是NSURLCache或是AFN?

1、在IOS 5之后可以使用NSURLCache 进行http缓存,但是每次缓存的是原始数据,每一次使用的时候,需要将原始数据解析成UIImage,导致额外的数据解析和内存占用,AFN就是使用NSURLCache进行缓存的。

2、UIImageView中使用image对象的时候,图片的解码是在主线程中运行的!而SDWebImage会强制将解码操作放到子线程中。(PNG,jpeg图片对象,转换为位图对象)

3、使用NSCache作为内存缓存,避免了对象的重复copy,并且保存的是位图对象,避免了重复的解码。

4、SDWebImage 完全绕过了Http请求关于缓存的控制,大大加快了缓存速度。

根据图片的url缓存,所以一旦改变图片,必须改变地址?(不会去判断服务器关于缓存处理的response header )对于类似facebook 头像这样的例子,可以使用下面的方式,这种方式,会参考请求头。

5、提供了大量的关于图片的扩展选择。

当我们调用这个sd_setImageWithURL,这个方法的时候发生了什么?

1、停止所有和这个View相关的Operation。

这里还有一个operation 字典:UIView+WebCacheOperation  有一个关联对象,用来保存这个View相关的Operation


operation字典


UIView+WebCacheOperation的cancle 当前所有相关的Operation

(相关类的介绍:

UIImageView (WebCache):

1、提供相关的下载方法

UIView (WebCacheOperation)

1、提供与view相关的loadOperation(字典),可以通过这个字典取消该View相关的Operation)

2、SDWebImageManager的downloadImageWithURL的方法

(1)、非法Url判断

(2)、定义一个SDWebImageCombinedOperation,用这个Operation管理下载和缓存的Operation,并把它加到runningOperations中

(3)、产生缓存的key,这里的缓存的key,可以进行自定义


自定义缓存key

(相关类介绍:

SDWebImageOperation

1、定义的一个基础协议,带有cancle方法

SDWebImageCombinedOperation

1、混合Operation,包含缓存Operation还有管理下载Operation

SDWebImageManager

SDWebImageManager(单例)

1、中间层,调用缓存,和下载(管理所有的Operation)

2、提供SDWebImageManagerDelegate(作为扩展),还有三种block

)

3、SDImageCache的queryDiskCacheForKey方法,开始寻找磁盘缓存和内存缓存

(1)、内存缓存,使用的NSCache(避免重复拷贝)

(2)、一个IOQueue,进行磁盘缓存的查询,进行异步查询


在io队列里面异步查询

(3)、如果磁盘中存在这张图片,那么进行判断对应的图片格式(包括动态图)

设置图片的方向(Orientation),scale,并且进行解码工作。这里强制进行异步解码,将编码之后的图片格式(png,jpeg)转换成位图对象。


进行缓存查找操作

相关的类:

SDImageCache(单例)

1、缓存管理,缓存配置,缓存清理,缓存查找(异步执行)

2、内存缓存,使用的是位图,磁盘缓存使用的是编码之后的图片

UIImage (ForceDecode)

1、图片解码,相关格式图片图像,转换为位图对象

强制解码:将编码之后的image对象转换为位图(点阵图像或绘制图像,是由称作像素(图片元素)的单个点组成的)

一般下载或者从磁盘获取的图片是PNG或者JPG,这是经过编码压缩后的图片数据,不是位图,要把它们渲染到屏幕前就需要进行解码转成位图数据,而这个解码操作比较耗时,iOS默认是在主线程解码,所以SDWebImage将这个过程放到子线程了。

同时因为位图体积很大,所以磁盘缓存不会直接缓存位图数据,而是编码压缩后的PNG或JPG数据。

4、当没有缓存时候,使用SDWebImageDownloader进行下载,

(1)、将所有的callback放在一个字典数组中管理。(用url作为key)。

(2)、封装request对象,加入用户自带的一些配置

注:为了避免重复下载,默认,不进行NSUrlCache缓存,不使用系统的缓存


避免重复下载

(3)产生SDWebImageDownloaderOperation,下载操作

(4)设置这个operation 的相关属性,比如优先级,还有executionOrder,执行顺序(先进后出或是先进先出),(实现的方式,是通过Operation的相互依赖)


关于执行顺序的枚举值
执行顺序设定的实现

相关的类:

SDWebImageDownloader

1、图片下载类,图片的下载管理

2、提供大量扩展(下载设置)

SDWebImageDownloaderOptions

SDWebImageDownloaderExecutionOrder,下载的顺序

SDWebImageDownloaderProgressBlock

SDWebImageDownloaderCompletedBlock

SDWebImageDownloaderHeadersFilterBlock

maxConcurrentDownloads(最大并发数)

3、操作callBack使用的的调度方式, dispatch_barrier_sync,dispatch_barrier_async管理barrierQueue(类似于锁?),之后添加的Operation,会等这个任务执行之后才会继续执行

5、使用SDWebImageDownloaderOperation,进行下载,在下载过程中,调用progressBlock,下载结束,调用completeBlock。拿到网络数据,转成图片格式,设置方向,scale,进行图片解码,返回的图片是位图对象

管理下载操作,3版本使用的是NSURLConnection,之后使用的是NSURLSession(异步下载)

(1)、提供后台下载,开启运行循环(不然代理不能正常调用)

(2)在NSURLConnection的代理中,处理下载功能

(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 拿到服务器响应,判断是否正确下载

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data下载过程管理(调用progressBlock),这里提供边下载,边显示的功能

下载图片,进行异步的强制解码

6、回到SDWebImageManager,

(1)处理Image对象,如果实现了相关的代理方法就调用代理方法,

(2)之后使用imageCache,保存图片信息。位图对象直接保存到内存缓存中,编码图片,保存到磁盘中。(这里是否能在之前就直接保存到磁盘,节省一段图片编码的过程)。内存中保存位图,是为了避免重复解码。磁盘中保存编码之后的图片是为了节省空间。

(3)从全局的Operation字典,移除相关的Operation


将下载后的图片进行缓存

7、回到UIImageView (WebCache),回到主线程,设置图片,调用结束


更新UI,回到主线程

其他注意的点:

1、缓存清理,当收到这三个通知的时候进行缓存的清理


缓存清理的策略,这里的IO操作都是异步处理的。

(1)删除过期缓存(苹果官方规定最长的缓存周期是1周)

(2)计算当前缓存文件的总大小,比较设置的最大缓存,如果超出的话,那么就继续删除(按照缓存文件创建的顺序),直到小于最大缓存为止


缓存策略

2、SDWebImagePrefetcher,这个类,提供提前缓存图片的方法(可以用来作用于banner等),提供批量的下载。


3、对于UIView (WebCacheOperation),当我们移除Operation的时候,发生了什么?其实取消的是SDWebImageCombinedOperation

(1)、取消cacheOperation

(2)、执行cancelBlock,这里的cancleBlock,关闭的就是下载的Operation

(3)、将这个Operation,移除整个Operation字典



最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,783评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,396评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,834评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,036评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,035评论 5 362
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,242评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,727评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,376评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,415评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,463评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,140评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,734评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,809评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,028评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,521评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,119评论 2 341

推荐阅读更多精彩内容