[TOC]
SDWebImage 层级
SDWebImageHighLevelDiagram-
接口层(公开层、调用层):通过分类提供接口,作为一个过度类
- UIImageView+WebCache
- UIButton+WebCache
-
图片加载层:从缓存(内存、磁盘)、网络获取
- SDImageCache:从内存缓存、磁盘缓存中获取图片
- SDWebImageDownloader:根据URL下载图片
-
基础模块:工具、分类、以及图片的编解码、图片转换工具
SDWebImage 加载图片时序图
SDWebImageSequenceDiagram-
调用入口:
sd_setImageWithURL
,进入UIImageView (WebCache)
分类 -
UIImageView (WebCache)
内部方法调用:sd_internelSetImageWithURL
,当前版本调用的方式是[self setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
-
SDWebImageManager
开始加载图片:downloadWithURL: options: progress: completed:
-
从缓存中取图片:
queryDiskCacheForKey:done:
- 先从内存缓存中查找:
imageFromMemoryCacheForKey:
- 再从磁盘缓存中查找:
diskImageForKey:
- 如果找到了,会将图片存到内存缓存中,下一次就可以直接从内存缓存中取:
[self.memCache setObject:diskImage forKey:key cost:cost];
- 如果找到了,会将图片存到内存缓存中,下一次就可以直接从内存缓存中取:
- 先从内存缓存中查找:
-
如果缓存中取到图片,则直接返回缓存中的结果;如果没有则进行下一步
-
开始下载图片:
downloadImageWithURL: options: progress: completed:
-
获取网络数据
-
存储图片:
storeImage:recalculateFromImage:imageData:forKey:toDisk:
- 存储到内存缓存中:
[self.memCache setObject:image forKey:key cost:image.size.height * image.size.width * image.scale];
- 存储到磁盘缓存中:
[fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil];
- 存储到内存缓存中:
-
设置图片:
wself.image = image; [wself setNeedsLayout];
SDWebImageCache 缓存原理
SDWebImageCacheClassDiagram缓存配置 SDImageCacheConfig 类
关于缓存的配置类,这里存放了全局的缓存相关的配置
- shouldDisableiCloud:是否关闭云端备份
- shouldCacheImagesInMemory:是否使用内存缓存
- shouldUseWeakMemoryCache:是否使用周缓存,如果开启会开启一个 weak 的 maptable来存储图片
- maxDiskAge:最大保存到磁盘的时长
- maxDiskSize:保存缓存的最大尺寸
内存缓存 SDMemoryCache
-
SDMemoryCache 继承于 NSCache 类
- 可以使用 NSCache 相关特性
- 但是 NSCache 里面的内容什么时候释放,是由系统管控的
- 所以创建了一个 NSMapTable 类型的 weakCache
-
weakCache:NSMapTable(周缓存)
-
相对于 NSDictionary,提供更多的内存语义
-
key 必须遵循 NSCoping 协议。
-
备注是:
strong-weak cache
,这是个很有意思的地方,下面来看看神奇的它-
首先来到它的初始化方法
self.weakCache = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];
-
key:NSPointerFunctionsStrongMemory(强引用)
-
value:NSPointerFunctionsWeakMemory(弱引用)
-
说明什么呢?说明存在 NSMapTable 里面的值,不会对外部的对象的生命周期造成影响,当这个值不存在的时候,NSMapTable 就会释放它
-
-
存缓存
- shouldUseWeakMemoryCache之前,存到 NSCache 中;
- shouldUseWeakMemoryCache之后,存到 weakCache 中;
-
取缓存
- shouldUseWeakMemoryCache之前,先从 NSCache 中取,如果有,则使用
- shouldUseWeakMemoryCache之后,如果 NSCache 中没有,则从 weakCache 中取。同时会存到 NSCache 中,下次取会更快
-
可能会出现存两遍的问题,典型的空间换时间的策略
-
磁盘缓存
- 创建一个目录:
- 为每一个缓存文件生成一个文件名:MD5 文件名
SDWebImageLoader 下载原理
SDWebImageLoaderClassDiagramSDWebImageDownloader:下载类
- 如何控制下载队列的先后顺序
- SDWebImageDownloaderFIFOExecutionOrder:默认,先进先出,队列
- SDWebImageDownloaderLIFOExecutionOrder:后进先出,栈
实现原理:让已经存在 operationQueue 里面的 operation 依赖当前这个 operation,这样就能保证,最后创建的这个 operation 永远是最先执行的
if (self.config.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
for (NSOperation *pendingOperation in self.downloadQueue.operations) {
[pendingOperation addDependency:operation];
}
}
- 最大并发数
- maxConcurrentDownloads:默认 6个
- 超时时长
- downloadTimeout:默认 15s
- HTTPS
- urlCredential:设置安全证书
- username:证书账号
- password:证书密码
-
线程安全
都是通过 信号量 来控制的线程安全,这个用法很巧妙
#define SD_LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); #define SD_UNLOCK(lock) dispatch_semaphore_signal(lock);
SDWebImageDownloaderOperation:数据处理类
- NSURLSession
- 请求的发起、取消
- 这里主要是 NSURLSession 和 NSOperation 相关的知识
SDWebImage 的类图设计
若你要想要编码逻辑更加清晰,不妨看看这8张设计图;
若你要设计一个好的架构,不妨看看这8张设计图;
- 层级结构图:SDWebImageHighLevelDiagram
- 加载图片时序图:SDWebImageSequenceDiagram
- 上层接口接口:SDWebImageTopLevelClassDiagram
- 核心管理类:SDWebImageManagerClassDiagram
- 缓存结构图:SDWebImageCacheClassDiagram
- 下载图片类图:SDWebImageLoaderClassDiagram
- 图片编码类图:SDWebImageCodersClassDiagram
- 整体架构图:SDWebImageClassDiagram
网友评论