SDWebImage源码学习一:简介与架构

往期导航:

SDWebImage源码学习合集目录

简介

SDWebImage可以用来快速下载展示网络图片,最简单的使用只需要一行代码:

//var imageView: UIImageView!
//var imageURL: NSURL!
imageView.sd_setImage(with: imageURL)
复制代码

就可以给UIImageView设置网络图片,SD内部自行管理下载,缓存,解码,完全不用任何额外操作

稍微复杂点的用法可以自己配置图片下载的模式,缓存的逻辑,不同格式的解码器,数据加密等

在高级一点的用法,可以自定义下载器,自定义缓存器:包括磁盘缓存与内存缓存,自定义解码器

所有的这一切,SDWebImage内部都做了很好的封装与解耦,提供了很强大功能的同时也支持非常灵活的扩展,5.0后甚至可以通过添加插件来使用FLAnimatedImage,YYImage第三方库作为插件的方式集成进来一起使用。very牛逼!

学习SDWebImage的源码,可以学习他的架构设计,模块管理,内部的解耦思想,对项目架构设计有很好的启发。而且SD源码中带有很详细的文档说明,各个模块甚至还有类图说明,很方便学习他的设计原理。

宏观框架:

引用下SDWebImage官方的框架图:

来自官方GitHub

从上往下:

UI层

SD显示对UI层需要设置网络图片的控件进行了扩展,包括UIImageView,UIButton,NSButton(mscOS下),添加了便捷根据URL设置网络图片的方法,方法经过各种抽象,有最简单的设置一个URL,也有最复杂的设置URL,占位图,下载选项,下载上下文,进度回调,完成回调等,又因为这些控件的父类都是UIView,因此对UIView进行了扩展,来使用SDWebImageManager来对图片进行下载处理。

当UIImageView调用分类设置图片URL时,在分类方法中,会依赖到Indicator接口来设置进度指示器,以及Transition接口来设置图片展示时的动画效果,封装处理好下载所需的options与需要贯穿在整个下载过程中的context上下文后,分类中开始准备使用SDWebImageManager来进行图片获取,在这个过程中,注入了ImagePrefetcher图片预加载器接口,允许可以在UIImageView准备下载图片之前,先对即将要下载的URL集合进行预下载,预加载完成后会把图片缓存起来,这样在SDWebImageManager准备获取图片时,可以快速直接读取缓存图片,节省时间。

核心调度层

SD的核心是SDWebImageManager类,这个类依赖着ImageCache接口来管理缓存,ImageLoader接口来管理下载,在收到UI分类中的获取图片指令之后,SDWebImageManager通过调度持有的cacher与loader高效的进行图片的缓存与下载,同时可以使用options+context来配置缓存与下载的逻辑

缓存器

使用抽象接口SDImageCache来定义缓存器,提供高度自定义化的同时,提供同名的默认实现类,而每一个ImageCache接口又依赖于两个细化的缓存接口:SDMemoryCacheSDDiskCache,分别用来管理内存缓存与磁盘缓存,也分别提供了同名的默认实现类

SDMemoryCache:使用weak map table实现的内存缓存管理器,保存了需要缓存在内存中的Image对象,并可根据系统内存进行优化,在内存紧张时还会通过释放不被视图强持有的图片资源来减轻内存负担。

SDDiskCache:把图片的数据写入到磁盘缓存或者从磁盘读取缓存的数据来供UI层使用,并提供了多钟过期规则供自由选择使用,磁盘操作全部都在内部串行的IO队列上同步或者异步的执行,所有数据敏感的操作都进行的加锁保护,缓存的数据可以在网络图片下载完成后写入到磁盘,使用时读取Data并进行解码后返回给UI层使用,同时会顺便写入内存缓存来加快下次访问速度。

缓存器还提供SDImageCachesManager来管理多个缓存器,且这个manager本身也实现了缓存器接口,可以作为缓存器使用,sd内部会自动选择合适的缓存器来处理

下载器

使用抽象接口SDImageLoader来定义下载器,提供同名默认实现类,持有URLSesson来从网络下载图片,也可以使用Photos框架来异步从相册获取图片。

在下载网络图片时,使用Operation在下载队列执行下载任务,使用op复用技术来支持在对同一个url进行多次加载时,复用同一个下载op,节约资源开销。

提供SDImageLoadersManager来管理多个下载器,本身也实现了下载器接口,作为默认的下载器使用。

底层模块

除了上层的UI层扩展,底层还有很多其他的模块来协助工作。

工具扩展

包括对图片数据的定义,辅助绘图,动图处理等。

图片编解码

使用SDImageCoder接口定义编解码器,还有一些辅助类来协助图片的编解码操作,默认提供了IOCoder,HEICCoder,GIFCoder,ANimatedCoder,WebPCoder,APNGCoder等编解码器来快速对各种图片数据下载完成后进行解码操作供UI层展示,后者对Image进行编码操作后给缓存器缓存到磁盘使用。

还提供了SDImageCOdersManager来管理多个图片解码器,可以自动根据图片的类型选择合适的解码器使用,本身也实现了SDImageCoder协议,作为默认的解码器来使用。

图片变换器

使用SDImageTransformer接口定义图片变换器,允许在对图片解码完成之后,对Image进行变换得到新的Image来使用,比如对图片进行圆角处理,缩放处理等。

提供了SDImagePipelineTransformer管道变换器,来管理多个变换器,本身也实现了变换器接口,可以对管理的多个图片变换器以管道的形式来逐个处理图像。

图片解密器

基于安全设置,下载过来的图片数据可能是加密的,SD提供了SDWebImageDownloaderDecryptor接口定义图片数据解密器,方便快速实现自定义的解密器,对图片数据解码之前,会先异步对原数据进行解密操作之后再进行解码处理,默认提供了Base64解密器。

不过要注意的是解密器不支持进度图片下载,因为加密后的数据在部分下载过来时无法解密出部分图片信息,因此无法边下载边展示。

类结构

同样套用官方的最最最最最完整的类图:
(点击放大)
完整的类图

简单介绍一下:

  • UI层几个能展示图片的子view扩展依赖于UIView的扩展,在UIView的扩展中进行开始图片的加载
  • UIView的扩展依赖SDWebImageOptions来配置下载选项
  • UIView还依赖SDWebImageManager来进行图片的加载
  • SDWebImageManager聚合了SDWebImagePrefetcher来进行图片的预加载操作
  • SDWebImageManager依赖SDWebImageCombinedOperation进行对图片的下载解码混合任务的管理
  • SDWebImageOperation定义了可以取消的异步任务,另外有几个继承的子接口来实现不同的任务
    1. SDWebImageCombinedOperation接口用来聚合加载与缓存任务,
    2. SDWebImageDownloadToken从来管理网络下载任务
  • SDWebImageManager还聚合了SDImageCache与SDImageLoader接口来缓存,加载图片
  • SDImageCache组合了SDImageCacheConfig来设置缓存配置,依赖SDImageCache设置缓存选项
  • SDImageCache组合SDMemoryCache与SDDiskCache来管理内存、磁盘缓存,
  • SDWebImageDownloader实现了SDImageLoader接口来下载图片,并依赖SDWebImageDownloadToken与SDWebImageDownloaderOperation来管理下载任务
  • SDWebImageDownloader组合了SDWebImageDownloaderConfig来设置下载配置,依赖SDWebImageDownloaderOptions设置下载选项
  • SDWebImageDownloader组合了request modifier与response modifier来修改下载请求与相应数据
  • SDImageCache与SDWebImageDownloader都依赖SDImageCoder来编解码图片,而SDImageCoder接口有两个继承接口:SDProgressiveImageCoder用来进度编解码静态图,SDAnimatedImageCoder用来编解码gif, 这两个接口都有好几个默认实现
  • SDWebImageCachKeyFilter接口用来对缓存key进行修改处理
  • SDWebImageCacheSerializer接口用来对缓存数据在保存到磁盘前,对数据进行序列化处理
  • SDImageTransformer接口用来对图片进行变换处理,有一大堆默认实现
  • SDWebImageIndicator接口定义了下载图片是的进度指示器

以上就是个人对SDWebImage框架的初步了解,后续会一个个模块的学习分析下框架的设计理念,并记录下个人的见解,如有错误,欢迎评论指正~感激不尽~

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享