SDWebImage源码分析
2017-08-22 14:50
211 查看
源码阅读目的
古语说的好“读书破万卷,下笔犹如神”,源码阅读就是一个挖掘别人思路,获取他人精华的一个途径。源码阅读就是站在别人的肩膀上,让自己看的更远。源码阅读对于提高coder的技术水平是非常重要的一个过程。“取其精华,去其糟粕”。所以需要读一些经典的源码,提高自身的实力。世人都说阅读源代码对于功力的提升是十分显著的。
源码主要功能
基本概述
SDWebImage的作用是实现对网络图片的异步下载以及提供图片缓存机制,不影响系统主线程的正常工作。 “This library provides an async image downloader with cache support.”
网络图片下载
SDWebImage开启新线程对图片进行异步下载,不影响系统主线程的正常执行。框架提供了一个下载队列,管理对图片的下载操作。
图片的缓存
SDWebImage对下载过的图片进行了缓存,在一定时间内避免重复下载。直接读取本地或者内存的图片,无需重新下载。
图片的解码
SDWebImage对下载的图片进行重新解码,将二进制数据变成UIImage数据。
源码架构体系
写软件需要有个编写思想:模块化,高内聚,可扩展。我们看到许多优秀的框架都会有这些软件思想。
基本流程
我们这里以UIImageView作为案例,当然SDWebImage也可以用在UIButton,MKAnimationView中,框架对这些控件也增加了相应的分类。 这个框架的设计还是很简洁和优雅,主要的功能只需要一行代码,
[self.imageView sd_setImageWithURL:[NSURL URLWithString:@"url"] placeholderImage:[UIImage imageNamed:@"placeholder.png"]]
其他复杂的实现全部被封装在框架中了,借用别人写的:“麻烦留给自己,方便给别人”。这也是在项目合作中经常遇到的情况,自己负责的模块,对外尽量简洁明了,提供给别人需要的,不需要的无需暴露给调用者。
源码框架
SDWebImage 主要包括两方面:图片缓存模块和图片下载模块。该框架采用逐层封装的一个过程。接近调用的一层是高层抽象,与调用者距离最远的是底层实现。如同操作系统的封装是一个模式,底层对细节的具体实现,高层则是最接近使用者的一层,呈现使用者的需要的内容。该框架的一个结构如下图
源码细节剖析
在加载图片的方法中为何首先调用 [self sd_cancelCurrentImageLoad]?
- (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { [self sd_cancelCurrentImageLoad]; ….. }
UIImageView在每次加载图片的时候都会产生一个操作Operation,并且将该Opeartion与当前的ImageView进行绑定。因为下载操作都是异步进行的,要确保 在同一时刻只有一个下载操作与当前的UIImageView进行捆绑,因此首先解除该UIImageView与上一个操作的捆绑。
如何避免对同一个URL同一时刻的多次请求?
框架在使用了一个以请求URL为key的字典容器来维护当前的下载,在下载模块SDWebImageDownloader,实现将下载任务的回调放到一个字典容器中,判断当前的key若字典中存在key-value键值对,则表明该URL不是第一次 发起请求,只是将对该请求的blocks回调放在字典容器中,但是不进行新的网络请求,因为已经存在一个对该URL的下载操作了。
BOOL first = NO; if (!self.URLCallbacks[url]) { self.URLCallbacks[url] = [NSMutableArray new]; first = YES; } // Handle single download of simultaneous download request for the same URL NSMutableArray *callbacksForURL = self.URLCallbacks[url]; NSMutableDictionary *callbacks = [NSMutableDictionary new]; if (progressBlock) callbacks[kProgressCallbackKey] = [progressBlock copy]; if (completedBlock) callbacks[kCompletedCallbackKey] = [completedBlock copy]; [callbacksForURL addObject:callbacks]; self.URLCallbacks[url] = callbacksForURL; if (first) { createCallback(); }
源码涉及技术点
NSOperationQueue线程操作NSOperation
GCD
网络请求(URLSession和NSURLTask)
大量的Blocks的使用
可选性(NS_OPTIONS)的使用
系统框架ImageIO的使用
多个回调的使用
NSCache
对UIImage支出的图片类型(文件类型:gif,png,jpeg,webp)的底层细节的实现
使用内联函数以及内联函数的作用
常量定义以k开头
需要深入研究的相关技术点
ImageIO部分CoreGraphic
图片相关的底层实现
其他学习到内容
代码的书写风格
每一个函数实现单一功能,不要把多个功能的代码放在一个函数中。SDK的编写格式
最少知道原则(迪米特原则)
暴露给调用者需要用的接口,不需要的无需呈现给用户。
.h中函数的注释说明
/** * 函数功能的描述 * * @param 参数名A 对该参数A的说明 * @param 参数名B 对该参数B的说明 * * @return 对返回值得说明 */
相关文章推荐
- iOS缓存 NSCache详解及SDWebImage缓存策略源码分析
- SDWebImage源码分析
- SDWebImage 源码分析
- SDWebImage源码分析(-)
- SDWebImage源码分析(二)
- SDWebImage源码分析
- SDWebImage源码分析
- SDWebImage源码分析
- SDWebImage 源码分析 --加载gif图片
- SDWebImage源码分析
- 【原】SDWebImage源码阅读(二)
- SDWebImage源码解读之 分类
- IOS SDWebImage 2.X源码阅读(一)
- iOS----------SDWebimage源码解析(1)
- SDWebImage源码研究与学习
- 图片缓存SDWebImage分析
- iOS开源库源码解析之SDWebImage
- SDWebImage使用详解及流程分析
- 【原】SDWebImage源码阅读(五)
- SDWebImage源码解读之 干货大总结