SDWebImage4.0.0 源码解析

在开发iOS的客户端应用时,经常需要从服务器下载图片,虽然系统提供了下载工具:NSData、NSURLSession等等方法,但是考虑到图片下载过程中,需要考虑的因素比较多,比如:异步下载、图片缓存、错误处理、编码解码等,以及实际需要中根据不同网络加载不同画质的图片等等需求,因此下载操作不是一个简单的下载动作就可以解决。

针对上述问题,目前常用的开源库就是SDWebImage,它很好的解决了图片的异步下载、图片缓存、错误处理等问题,得到了广泛的应用,使得设置UIImageViewUIButton对象的图片十分方便。本文就从源码的角度,剖析一下这款优秀的开源库的具体实现。

类结构图

SDWebImage的源码的类结构图和下载流程图在官方的说明文档里有介绍,通过UML类结构图详细的介绍了该框架的内部结构,以及通过流程图介绍了具体的下载过程。

下图是我总结的SDWebImage的结构图,简单的把SDWebImage源码文件按照功能进行了划分,方便在阅读源码时,能快速的对源码有一个总体的认识,加快阅读效率。



关键类功能简介:

  • 1.下载类

SDWebImageDownloader:提供下载的方法给SDWebImageManager使用,提供了最大并发量的下载控制、超时时间、取消下载、下载挂起、是否解压图片等等功能。同时,还提供了开始下载和停止下载的通知,给使用者监测下载状态,如果使用者不用监测下载状态,就不用监测该通知,这种设计模式很灵活,给使用者提供了更方便的选择。

SDWebImageDownloaderOperation:继承自NSOperation,是图片下载的具体实现类,通过加入到NSOperationQueue中,然后在start方法中来开启下载操作。

  • 2.图片缓存

SDImageCacheConfig:主要提供缓存的配置信息,如:是否解压图片、是否缓存到内存、最大缓存时间(默认是一周)和最大缓存的字节数等等。

SDImageCache:缓存实现类,提供最大缓存字节、最大缓存条目的控制,以及缓存到内存及磁盘、从内存或磁盘删除、查询检索和查询缓存信息等功能。

  • 3.分类

UIImageView+WebCacheUIImageView的分类,提供了设置UIImageView对象图片的多种方法,下面的方法可以说是SDWebImage框架中最常用的方法。

UIButton+WebCacheUIButton的分类,提供了设置按钮图片和按钮背景图片的功能

  • 4.工具类

SDWebImageDecoder:图像解码的工具类,通过imageNames:加载图片会立即进行解码,而通过imageWithContentsOfFile:则不会

SDWebImagePrefetcher:批量图像下载工具,针对UI界面中需要下载多个图片时,又要在滑动中保持流畅体验,则可以使用该工具类批量下载图片,然后在给具体的UI控件设置图片时,就会直接从缓存中取

SDWebImageManager:下载管理类工具,是SDWebImage的核心类,从官方文档的类图中也可以看出,提供了查看图片是否已经缓存、下载图片、缓存图片、取消所有的下载等等功能

  • 5.图片格式类

NSData+ImageContentType:根据图片数据的第一个字节来获取图片的格式,可以区分PNGJPEGGIFTIFFWebP

以上只是对SDWebImage类结构图的简单分析,如果需要进一步了解各个类的具体实现,请参考文末的资料,已有人详细的介绍了各个类的功能实现原理或方法。

应用

下面介绍一个在应用SDWebImage设置UI图片的源码实现过程

在UIImageView上的应用

设置图片

通过设置URL、占位图片、图片配置、图片下载进度回调和设置完成回调来给UIImageView对象设置图片

上述代码调用UIImageView+WebCache.m里的方法

然后调用UIView+WebCache.m中的方法获取图片,然后根据option的类型进行不同的设置

加载图片的具体实现代码在SDWebImageManager里面,先从缓存中取图片,如果缓存中没有图片,就从网络下载,然后设置图片,最后再缓存该图片

从缓存中取图片,是先从内存中取,如果在内存中取到,就在当前线程中直接回调doneBlock;如果内存中没有,就开子线程从磁盘中取,如果取到图片,就回调doneBlock

图片的下载过程是在SDWebImageDownloader.m中进行的,实质是通过SDWebImageDownloaderOperation(继承自NSOperation)对象,把该对象加入到downloadQueue里,然后在start方法里通过NSURLSession来下载图片。(其中,NSOperation有两个方法:mainstart,如果想使用同步,那么最简单方法的就是把逻辑写在main()中,使用异步,需要把逻辑写到start()中,然后加入到队列之中)

SDWebImageDownloaderOperation对象加入到操作队列,就开始调用该对象的start方法。

在下载过程中,会涉及鉴权、响应的statusCode判断(404304等等),以及收到数据后的进度回调等等,在最后的didCompleteWithError里做最后的处理,然后回调完成的block,下面仅分析一下didCompleteWithError的方法

以上就是给UIImageView对象设置图片的过程,可以看出还是比较复杂的,考虑的情况也比较多,不得不佩服作者的编码能力。至于UIButton的图片设置过程,分析情况类似,在此不做分析。

SDWebImage的源码中在设置图片的过程中,还应用了多种技术:GCD的线程组、锁机制、并发控制、队列、图像解码、缓存控制等等,是一个综合性十分强的项目了,通过阅读源码,对这些技术的使用也有了进一步的认知,对作者的编程功力的深厚深深折服。


SDWebImage的解析到此结束,本文只是简单的从源码结构、UIImageView的使用角度进行了简单的分析,希望对阅读源码的朋友有一些帮助,如果文中有不足之处,还望不吝指出,互相学习。

参考资料

SDWebImage源码

SDWebImage源码解读

SDWebImage源码(一)——SDWebImage概览

iOS开发——你真的会用SDWebImage?

感觉不错,打个赏?
微信                                 支付宝
pay_weixin            pay_zhifubao
金额随意 快来“”我呀~
联系方式:kelvin@fishbay.cn

发表评论

电子邮件地址不会被公开。 必填项已用*标注