SDWebImage源码阅读(五)SDImageCacheConfig/SDImageCache(上)
SDImageCache 是 SDWebImage 用来处理图片缓存的类。
在看 SDImageCache 类之前,先分析一下 SDImageCacheConfig 类,它是用来管理缓存配置信息的。
SDImageCacheConfig.h
1 @interface SDImageCacheConfig : NSObject 2 3 /** 4 * Decompressing images that are downloaded and cached can improve performance but can consume lot of memory. 5 * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption. 6 */ 7 @property (assign, nonatomic) BOOL shouldDecompressImages; 8 9 /** 10 * disable iCloud backup [defaults to YES] 11 */ 12 @property (assign, nonatomic) BOOL shouldDisableiCloud; 13 14 /** 15 * use memory cache [defaults to YES] 16 */ 17 @property (assign, nonatomic) BOOL shouldCacheImagesInMemory; 18 19 /** 20 * The maximum length of time to keep an image in the cache, in seconds 21 */ 22 @property (assign, nonatomic) NSInteger maxCacheAge; 23 24 /** 25 * The maximum size of the cache, in bytes. 26 */ 27 @property (assign, nonatomic) NSUInteger maxCacheSize; 28 29 @end
解压缩图像下载和缓存可以提高性能,但是会消耗大量内存, 默认是YES ,如果因为消耗内存过大而崩溃,可以置为NO。
shouldDecompressImages 是否解压图像,默认是 YES
shouldDisableiCloud 是否禁用 iCloud 备份,默认是 YES
shouldCacheImagesInMemory 是否缓存到内存中,默认是YES
maxCacheAge 在缓存中图像保存时间的最大长度,以秒为单位 默认是一周时间
maxCacheSize 缓存的最大大小,以字节为单位
SDImageCacheConfig.m
1 static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week 2 3 @implementation SDImageCacheConfig 4 5 - (instancetype)init { 6 if (self = [super init]) { 7 _shouldDecompressImages = YES; 8 _shouldDisableiCloud = YES; 9 _shouldCacheImagesInMemory = YES; 10 _maxCacheAge = kDefaultCacheMaxCacheAge; 11 _maxCacheSize = 0; 12 } 13 return self; 14 } 15 16 @end
静态不可变 NSInteger 类型的 kDefaultCacheMaxCacheAge 表示在缓存中图像保存时间的最大长度,以秒为单位 默认是一周时间(60 * 60 * 24 * 7)。
下面是重写类的 init 方法,分别为.h 中定义的属性赋初值。SDImageCacheConfig 就这么多内容,下面看SDImageCache。
SDImageCache.h
1.枚举 SDImageCacheType 缓存类型(缓存位置)
1 typedef NS_ENUM(NSInteger, SDImageCacheType) { 2 /** 3 * The image wasn't available the SDWebImage caches, but was downloaded from the web. 4 */ 5 SDImageCacheTypeNone, 6 /** 7 * The image was obtained from the disk cache. 8 */ 9 SDImageCacheTypeDisk, 10 /** 11 * The image was obtained from the memory cache. 12 */ 13 SDImageCacheTypeMemory 14 };
定义了一个枚举来分类表示:
SDImageCacheTypeNone:图像不能用 SDWebImage 缓存,但能从网上下载。
SDImageCacheTypeDisk:从磁盘中获取图像,图像在磁盘中缓存。
SDImageCacheTypeMemory:从内存中获取图像,图像在内存中缓存。
2.定义了3个block
1 typedef void(^SDCacheQueryCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType); 2 3 typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache); 4 5 typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger totalSize);
3.属性Properties
1 /** 2 * Cache Config object - storing all kind of settings 3 */ 4 @property (nonatomic, nonnull, readonly) SDImageCacheConfig *config;
缓存配置对象,存储所有设置。
1 /** 2 * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory. 3 */ 4 @property (assign, nonatomic) NSUInteger maxMemoryCost;
内存中的最大缓存容量,以像素为单位。
1 /** 2 * The maximum number of objects the cache should hold. 3 */ 4 @property (assign, nonatomic) NSUInteger maxMemoryCountLimit;
设置内存缓存中的最大数量。
4.单例和初始化Singleton and initialization
1 /** 2 * Returns global shared cache instance 3 * 4 * @return SDImageCache global instance 5 */ 6 + (nonnull instancetype)sharedImageCache; 7 8 /** 9 * Init a new cache store with a specific namespace 10 * 11 * @param ns The namespace to use for this cache store 12 */ 13 - (nonnull instancetype)initWithNamespace:(nonnull NSString *)ns; 14 15 /** 16 * Init a new cache store with a specific namespace and directory 17 * 18 * @param ns The namespace to use for this cache store 19 * @param directory Directory to cache disk images in 20 */ 21 - (nonnull instancetype)initWithNamespace:(nonnull NSString *)ns 22 diskCacheDirectory:(nonnull NSString *)directory NS_DESIGNATED_INITIALIZER;
管理类一般都会创建全局的单例对象,同时根据不同的业务需求设计不同的初始化方法,不管是什么样的类,在设计它的时候,应该通过合理的初始化方法告诉开发者该类应该如何创建。
+ (nonnull instancetype)sharedImageCache; 返回一个全局的缓存实例(SDImageCache)
- (nonnull instancetype)initWithNamespace:(nonnull NSString *)ns; 初始化一个特定 namespace 的缓存实例(SDImageCache)
- (nonnull instancetype)initWithNamespace:(nonnull NSString *)ns diskCacheDirectory:(nonnull NSString *)directory NS_DESIGNATED_INITIALIZER; 初始化一个特定 namespace 和磁盘缓存目录的缓存实例(SDImageCache)
NS_DESIGNATED_INITIALIZER 如果想设置某个方法为指定的初始化方法,通过NS_DESIGNATED_INITIALIZER
来实现。
5.Cache paths
1 - (nullable NSString *)makeDiskCachePath:(nonnull NSString*)fullNamespace; 2 3 /** 4 * Add a read-only cache path to search for images pre-cached by SDImageCache 5 * Useful if you want to bundle pre-loaded images with your app 6 * 7 * @param path The path to use for this read-only cache path 8 */ 9 - (void)addReadOnlyCachePath:(nonnull NSString *)path;
把图像缓存到了磁盘中,那么就应该提供一个方法获得这个缓存路径。
- (nullable NSString *)makeDiskCachePath:(nonnull NSString*)fullNamespace; 这个方法正是传入一个 fullNamespace 返回该命名空间对应的缓存路径。
- (void)addReadOnlyCachePath:(nonnull NSString *)path; 添加一个只读路径到 SDWebImage 的预缓存路径集合里面去,保证当搜索本地图像的时候搜索所有的缓存路径。
注意:在开发中,会遇到这样的情况,假如之前把图片缓存到了地址1
,现在打算重构代码。写了这么一个缓存管理者,需要和之前的缓存的图片建立联系,但是以后都打算使用新写的这个管理者,那怎么办呢??
只需要把之前的路径添加到管理类的路径集合中就行了。主要目的是在搜索图片的时候,也有权限去搜索新添加的路径。
6.Store Ops
1 /** 2 * Asynchronously store an image into memory and disk cache at the given key. 3 * 4 * @param image The image to store 5 * @param key The unique image cache key, usually it's image absolute URL 6 * @param completionBlock A block executed after the operation is finished 7 */ 8 - (void)storeImage:(nullable UIImage *)image 9 forKey:(nullable NSString *)key 10 completion:(nullable SDWebImageNoParamsBlock)completionBlock; 11 12 /** 13 * Asynchronously store an image into memory and disk cache at the given key. 14 * 15 * @param image The image to store 16 * @param key The unique image cache key, usually it's image absolute URL 17 * @param toDisk Store the image to disk cache if YES 18 * @param completionBlock A block executed after the operation is finished 19 */ 20 - (void)storeImage:(nullable UIImage *)image 21 forKey:(nullable NSString *)key 22 toDisk:(BOOL)toDisk 23 completion:(nullable SDWebImageNoParamsBlock)completionBlock; 24 25 /** 26 * Asynchronously store an image into memory and disk cache at the given key. 27 * 28 * @param image The image to store 29 * @param imageData The image data as returned by the server, this representation will be used for disk storage 30 * instead of converting the given image object into a storable/compressed image format in order 31 * to save quality and CPU 32 * @param key The unique image cache key, usually it's image absolute URL 33 * @param toDisk Store the image to disk cache if YES 34 * @param completionBlock A block executed after the operation is finished 35 */ 36 - (void)storeImage:(nullable UIImage *)image 37 imageData:(nullable NSData *)imageData 38 forKey:(nullable NSString *)key 39 toDisk:(BOOL)toDisk 40 completion:(nullable SDWebImageNoParamsBlock)completionBlock; 41 42 /** 43 * Synchronously store image NSData into disk cache at the given key. 44 * 45 * @warning This method is synchronous, make sure to call it from the ioQueue 46 * 47 * @param imageData The image data to store 48 * @param key The unique image cache key, usually it's image absolute URL 49 */ 50 - (void)storeImageDataToDisk:(nullable NSData *)imageData forKey:(nullable NSString *)key;
这部分的函数方法主要用来存储图片的。
- (void)storeImage:(nullable UIImage *)image forKey:(nullable NSString *)key completion:(nullable SDWebImageNoParamsBlock)completionBlock;
异步将图像存储在给定键的内存和磁盘缓存中。默认是内存和磁盘都缓存图像的。
image 是需要存储的图片,key 是该图片的唯一标识,通常是使用图片的绝对URL,completionBlock 是图片存储完毕后的 block 回调。SDWebImageNoParamsBlock 是在 SDWebImageCompat 里面定义的无参数返回值为 void 的 block。
1 typedef void(^SDWebImageNoParamsBlock)();
- (void)storeImage:(nullable UIImage *)image forKey:(nullable NSString *)key toDisk:(BOOL)toDisk completion:(nullable SDWebImageNoParamsBlock)completionBlock;
这个函数和上面的类似,只是加了一个名字为 toDisk 的布尔类型的参数,如果是 YES 的时候存储图像到磁盘缓存中。
- (void)storeImage:(nullable UIImage *)image imageData:(nullable NSData *)imageData forKey:(nullable NSString *)key toDisk:(BOOL)toDisk completion:(nullable SDWebImageNoParamsBlock)completionBlock;
这个函数和上面的类似,只是加了一个名字为 imageData 的 NSData 类型的参数,imageData 表示由服务器返回的图像数据,将用于磁盘缓存,而不是直接保存或者压缩 image 对象。
- (void)storeImageDataToDisk:(nullable NSData *)imageData forKey:(nullable NSString *)key;
同步存储图像的 NSData 数据到磁盘缓存中,并以 key 作为图像数据的唯一标识。注意这个方法是同步的,要注意在 ioQueue 中回调它。
图像存储过程的设计中有下边这几个需要考虑的因素:
- 数据源:可以保存 UIImage 也可以保存 NSData
- 唯一标识:找到该数据的唯一标识,一般使用图片的 URL
- 是否需要保存到硬盘:根据配置文件中的设置,如果设置了应该缓存到内存,那么图片肯定会被缓存到内存中。
- 数据保存这一过程必须是异步的,在完成之后,在主线程回调
7.Query and Retrieve Ops
1 /** 2 * Async check if image exists in disk cache already (does not load the image) 3 * 4 * @param key the key describing the url 5 * @param completionBlock the block to be executed when the check is done. 6 * @note the completion block will be always executed on the main queue 7 */ 8 - (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock; 9 10 /** 11 * Operation that queries the cache asynchronously and call the completion when done. 12 * 13 * @param key The unique key used to store the wanted image 14 * @param doneBlock The completion block. Will not get called if the operation is cancelled 15 * 16 * @return a NSOperation instance containing the cache op 17 */ 18 - (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock; 19 20 /** 21 * Query the memory cache synchronously. 22 * 23 * @param key The unique key used to store the image 24 */ 25 - (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key; 26 27 /** 28 * Query the disk cache synchronously. 29 * 30 * @param key The unique key used to store the image 31 */ 32 - (nullable UIImage *)imageFromDiskCacheForKey:(nullable NSString *)key; 33 34 /** 35 * Query the cache (memory and or disk) synchronously after checking the memory cache. 36 * 37 * @param key The unique key used to store the image 38 */ 39 - (nullable UIImage *)imageFromCacheForKey:(nullable NSString *)key;
查询和检索图像的操作。对于如何获取图像,有很多方式,不过首先要选择的是图像来源,是从内存缓存还是磁盘缓存,然后选择是异步操作还是同步操作,如果选择异步操作,则就要使用 block 。
- (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock;
通过传入的 Key(图像和图像数据的唯一标识)值异步检测图像是否已经存在于磁盘缓存中(不加载图像),在检测完毕后会回调 completionBlock ( typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache); )
没有返回值。
注意:这个检测完成的 block 始终是位于主线程执行的。
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock;
异步查询缓存中是否存在图像并在查询完成后回调完成的block。doneBlock 这个完成的回调block(typedef void(^SDCacheQueryCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType); 这个block 有三个参数,查询到的 image 和 image 的 NSData 类型的数据,以及 image 的缓存类型,是在内存还是在磁盘)如果操作在完成之前被取消则该block 不会执行。
返回值是一个包含缓存操作的 NSOperation 实例,原因是在内存中获取耗时非常短,在磁盘中时间相对较长。
- (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key;
根据传入的图像的唯一标识符 key 同步查询内存缓存。
返回值是查询到的图像。
- (nullable UIImage *)imageFromDiskCacheForKey:(nullable NSString *)key;
根据传入的图像的唯一标识符 key 同步查询磁盘缓存。
返回值是查询到的图像。
- (nullable UIImage *)imageFromCacheForKey:(nullable NSString *)key;
根据传入的图像的唯一标识符 key 同步查询缓存(包括内存和磁盘),先去查询内存缓存然后在查询磁盘缓存。
返回值是查询到的图像。
8.Remove Ops
1 /** 2 * Remove the image from memory and disk cache asynchronously 3 * 4 * @param key The unique image cache key 5 * @param completion A block that should be executed after the image has been removed (optional) 6 */ 7 - (void)removeImageForKey:(nullable NSString *)key withCompletion:(nullable SDWebImageNoParamsBlock)completion; 8 9 /** 10 * Remove the image from memory and optionally disk cache asynchronously 11 * 12 * @param key The unique image cache key 13 * @param fromDisk Also remove cache entry from disk if YES 14 * @param completion A block that should be executed after the image has been removed (optional) 15 */ 16 - (void)removeImageForKey:(nullable NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(nullable SDWebImageNoParamsBlock)completion;
移除某个图像,图像数据可能存在内存里面或者存在磁盘里面,也或者内存和磁盘里面同时存在。那删除图像数据的时候就要针对不同的情况分别删除了。
- (void)removeImageForKey:(nullable NSString *)key withCompletion:(nullable SDWebImageNoParamsBlock)completion;
根据传入的 key 从内存缓存和磁盘缓存异步删除图像。在图像移除后会回调 completion (typedef void(^SDWebImageNoParamsBlock)();)该 block 的实现与否是可选的。
函数的返回值是 void。
- (void)removeImageForKey:(nullable NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(nullable SDWebImageNoParamsBlock)completion;
该方法和上面一样也是异步删除图像,但是这个方法加了一个布尔类型的变量 fromDisk 表示是否也同时从磁盘缓存删除图像,如果是YES 则表示内存缓存和磁盘缓存都删除。在图像移除后会回调 completion (typedef void(^SDWebImageNoParamsBlock)();)该 block 的实现与否是可选的。
9.Cache clean Ops
1 /** 2 * Clear all memory cached images 3 */ 4 - (void)clearMemory; 5 6 /** 7 * Async clear all disk cached images. Non-blocking method - returns immediately. 8 * @param completion A block that should be executed after cache expiration completes (optional) 9 */ 10 - (void)clearDiskOnCompletion:(nullable SDWebImageNoParamsBlock)completion; 11 12 /** 13 * Async remove all expired cached image from disk. Non-blocking method - returns immediately. 14 * @param completionBlock A block that should be executed after cache expiration completes (optional) 15 */ 16 - (void)deleteOldFilesWithCompletionBlock:(nullable SDWebImageNoParamsBlock)completionBlock;
移除数据,这里的移除和上面的移除图像不同,上面是根据指定的 key 去移除指定的图像,这里则是基本针对所有图像或者符合移除条件的多个图片去做移除操作。
- (void)clearMemory;
清空内存中缓存的所有图片。
- (void)clearDiskOnCompletion:(nullable SDWebImageNoParamsBlock)completion;
异步清除所有磁盘缓存图像。非阻塞方法-立即返回。completion (typedef void(^SDWebImageNoParamsBlock)();)应在缓存过期完成后执行。该 block 的实现与否是可选的。
- (void)deleteOldFilesWithCompletionBlock:(nullable SDWebImageNoParamsBlock)completionBlock;
从磁盘中异步移除所有过期缓存的图像。非阻塞方法-立即返回。completionBlock (typedef void(^SDWebImageNoParamsBlock)();)应在缓存过期完成后执行。该 block 的实现与否是可选的。
10.Cache Info
1 /** 2 * Get the size used by the disk cache 3 */ 4 - (NSUInteger)getSize; 5 6 /** 7 * Get the number of images in the disk cache 8 */ 9 - (NSUInteger)getDiskCount; 10 11 /** 12 * Asynchronously calculate the disk cache's size. 13 */ 14 - (void)calculateSizeWithCompletionBlock:(nullable SDWebImageCalculateSizeBlock)completionBlock;
缓存的相关信息。
- (NSUInteger)getSize;
获取磁盘缓存所使用的大小。单位是字节(Byte)。
- (NSUInteger)getDiskCount;
获取磁盘缓存中图像的数量。
- (void)calculateSizeWithCompletionBlock:(nullable SDWebImageCalculateSizeBlock)completionBlock;
异步计算磁盘缓存大小。completionBlock(typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger totalSize);)会在异步计算完成后回调。
11.Cache Paths
1 /** 2 * Get the cache path for a certain key (needs the cache path root folder) 3 * 4 * @param key the key (can be obtained from url using cacheKeyForURL) 5 * @param path the cache path root folder 6 * 7 * @return the cache path 8 */ 9 - (nullable NSString *)cachePathForKey:(nullable NSString *)key inPath:(nonnull NSString *)path; 10 11 /** 12 * Get the default cache path for a certain key 13 * 14 * @param key the key (can be obtained from url using cacheKeyForURL) 15 * 16 * @return the default cache path 17 */ 18 - (nullable NSString *)defaultCachePathForKey:(nullable NSString *)key;
获取图像的缓存路径。
- (nullable NSString *)cachePathForKey:(nullable NSString *)key inPath:(nonnull NSString *)path;
获取某个键的缓存路径(需要缓存路径根文件夹)。
根据传入的 key 和缓存路径的根文件夹的路径 path ,返回 key 指定的图像的完整路径。
- (nullable NSString *)defaultCachePathForKey:(nullable NSString *)key;
获取某个键的默认缓存路径。
到这里 SDImageCache.h 文件已经分析完毕。先告一段落,.m 函数实现文件,在下一篇分析。
参考链接:http://www.jianshu.com/p/b3eff8304b37
END