本文正在参加「金石计划 . 瓜分6万现金大奖」
前言
- 图片缓存在iOS端我们可能每天都会使用,
Objective-C
中有SDWebImage,Swift中
有喵神的Kingfisher~ - 然而会使用框架提供的API只是表层, 如果想精进自己的框架设计能力, 我们还需要去研究框架源码, 以窥这些顶级开发者的设计思路.
- 下面就iOS中的图片缓存框架, 跟各位同仁聊一聊自己的浅见, 抛砖引玉.
- 文章纯手打, 抛砖引玉, 如有错误还请评论区指正, 先行谢过了:)
1. 一个合理的图片缓存框架应该考虑什么?
1.1 怎样设计一个图片缓存框架?
- 我们需要考虑以下几点:
-
- Manager
-
- 内存 磁盘 网络
-
- Code Manager
-
- 图片解码 图片压缩/解压缩
1.2 图片读写应该如何设计?
- 以图片URL的单向Hash值作为Key
- 开始 -> 内存是否命中
- YES -> 结束
- NO -> 磁盘是否命中
-
- YES -> 结束
-
- NO -> 网络下载 -> 结束
1.3 内存层面应该如何设计?
1.3.1 存储的Size
- 队头 队尾
- 50 x 10kb以下
- 20 x 100kb以下
- 10 x 100kb以上
1.3.2 图片的淘汰策略
- 以队列先进先出的方式淘汰
- LRU算法(如30分钟内是否使用过)
-
- 定时检查 提高检查触发频率
-
- 每次进行读写时 前后台切换时
-
- 这里一定注意开销!
1.3.3 磁盘存储层面的设计
- 存储方式
- 大小限制(如100MB)
- 淘汰策略(如某一图片存储时间距今已超过7天)
1.3.4 网络请求层面的设计
- 图片请求最大并发量
- 请求超时策略
- 请求优先级
1.3.5 图片解码层面的考量
- 对于不同格式的图片, 解码采用什么方式来做?
- 应用策略模式对不同图片格式进行解码
- 在哪个阶段做图片解码处理?
- 磁盘读取后 网络请求返回后
1.3.6 整体思路导图
2. iOS中的SDWebImage框架是怎么做缓存的?
- 采用了二级缓存策略, 图片缓存的时候, 在内存中有缓存, 在磁盘中也有缓存
- 内存缓存使用NSCache做的.
2.1 缓存步骤
- 下载图片, 将图片缓存在内存中
- 判断图片的格式为png或jpeg, 将图片转成NSData数据
- 获取图片的存储路径, 图片的文件名是通过传入key经过MD5加密后获得的
- 将图片存进磁盘中
2.2 如何获取图片
- 在内存缓存中找
- 如果内存中找不到, 去默认磁盘目录中找, 找不到在去自定义磁盘目录中找
- 如果磁盘中也找不到就会下载图片
- 获取图片数据之后, 根据图片类型将图片数据从NSData转成UIImage
- 默认对图片进行解压缩, 生成位图图片
- 将位图图片返回
2.3 图片是如何被解压缩的?
- 判断图片是否是动图, 如果是就不能解压缩
- 判断图片是否透明, 如果是, 不能解压缩
- 判断图片的颜色控件是不是RGB, 如果不是, 就不能解压缩
- 根据图片的大小创建一个上下文
- 将图片绘制在上下文中
- 从上下文中读取一个不透明的位图图像, 该图像就是解压缩后的图像
- 将位图图像返回
2.4 NSCache
NSCache
说白了就是做缓存专用的一个系统类- 类似可变字典一样, 但是
NSCache
是线程安全的, 系统类自动做好了加锁和释放锁等一系列的操作, -
- 还有一个重要的是如果内存不足的时候,
NSCache
会自动释放掉存储的对象, 不需要开发者手动干预.
- 还有一个重要的是如果内存不足的时候,
2.5 SDWebImage是如何解决tableView复用时出现图片错乱问题的?
- 错乱是在
UIImageView+WebCache
文件中这个方法每次都会调用[self sd_cancelCurrentImageLoad]
.
2.6 SDWebImage大致流程导图
3. 小结
- 图片缓存框架的设计思路及应用基本就是以上这些.
- 在使用这些框架的时候, 知道这些框架的设计思路, 可能也并不会提高太多开发效率.
- 认识框架底层背后的设计思路, 在我看来是提供了一种技术冗余积累.
- 因为, 你我都无法保证在三方框架的时候过程中, 可能会遇到什么突发情况.
- 然而知其所以然后, 我们在处理这些突发情况时, 就能更加从容:)
发文不易, 喜欢点赞的人更有好运气👍 :), 定期更新+关注不迷路~
ps:欢迎加入笔者18年建立的研究iOS审核及前沿技术的三千人扣群:662339934,坑位有限,备注“掘金网友”可被群管通过~
本文正在参加「金石计划 . 瓜分6万现金大奖」