###背景
SDWebImage是iOS开发过程中最常使用的一个网络图片库,包括图片的下载和缓存。
主要提供的功能如下:
1.提供UIImageView, UIButton, MKAnnotationView 的分类,用来加载网络图片,并进行缓存管理;
2.异步方式来下载网络图片
3.异步方式: memory (内存)+ disk (磁盘) 来缓存网络图片,LRU自动管理缓存;
4.后台图片解码,转换及压缩;
5.同一个 URL 不会重复下载;
6.失效的 URL 不会被无限重试;
7.支持 GIF动画 及 WebP 格式;
8.使用 GCD 和 ARC;
9.开启子线程进行耗时操作,不阻塞主线程;
###入口部分
在使用SDWebImage的时候,入口如下:
点进去,可以看到下面这些方法:
作为入口函数,在 sd_setImageWithURL 方法中采用了多种参数灵活搭配的同名方法。而内部实质,都在向最后一个 sd_setImageWithURL 传入参数最多的方法进行调用处理。可以清晰的梳理函数构造逻辑,减轻代码编写量。
###下载部分
整个下载管理器对于下载请求的管理都是放在downloadImageWithURL:options:progress:completed:方法里面来处理的,该方法调用了上面所提到的addProgressCallback:andCompletedBlock:forURL:createCallback:方法来将请求的信息存入管理器中,同时在创建回调的block中创建新的操作,配置之后将其放入downloadQueue操作队列中,最后方法返回新创建的操作。每个下载操作的超时时间可以通过downloadTimeout属性来设置,默认值为15秒。
其具体实现如下:
###缓存部分
为了减少网络流量的消耗,我们都希望下载下来的图片缓存到本地,下次再去获取同一张图片时,可以直接从本地获取,而不再从远程服务器获取。这样做的另一个好处是提升了用户体验,用户第二次查看同一幅图片时,能快速从本地获取图片直接呈现给用户。
SDWebImage提供了对图片缓存的支持,而该功能是由SDImageCache类来完成的。该类负责处理内存缓存及一个可选的磁盘缓存。其中磁盘缓存的写操作是异步的,这样就不会对UI操作造成影响。
缓存到了本地,怎么查找缓存呢?代码如下:
而部分清理则是根据我们设定的一些参数值来移除一些文件,这里主要有两个指标:文件的缓存有效期及最大缓存空间大小。文件的缓存有效期可以通过maxCacheAge属性来设置,默认是1周的时间。如果文件的缓存时间超过这个时间值,则将其移除。而最大缓存空间大小是通过maxCacheSize属性来设置的,如果所有缓存文件的总大小超过这一大小,则会按照文件最后修改时间的逆序,以每次一半的递归来移除那些过早的文件,直到缓存的实际大小小于我们设置的最大使用空间。清理的操作在-cleanDiskWithCompletionBlock:方法中,其实现如下:
###总结
1.把图片的解码工作放到子线程(SDWebImageDecoder)。
2.在主线程中完成重采样的工作。重采样算法一般有: Nearest Neighbour Resampling (最邻近重采样)、 Bilinear Resampling(双线性/两次线性重采样)、Bicubic Resampling (双立方/两次立方重采样)等。
3.利用空间换时间的做法,在子线程中解码图片并缓存位图结果,避免图片的重复解码,提升图片展示性能。如果列表中需要展示很多网络图片,SDWebImage这种做法,有利于提高列表的流畅度。
4.SDWebImage中下载的图片,即使解码缩放(decodedAndScaledDownImageWithImage:)后,图片大小未必和imageView的大小相同,这会引发重采样,我们可以在图片显示前,将图片裁剪成和imageView的大小相同,提升性能(一个小的优化点)。