SDWebImage实现原理

2020-04-28  本文已影响0人  Foxhoundsun

概念总成

image.png

从图上能看出,SD主要分为4个主要模块:

SDWebImageManager(管理类) 这个是SD的核心类,用于分配任务与管理任务。他一般不会直接参与任务的执行。而是把任务下发到下面两个功能类来做。体现了谁的任务谁做的解耦合思想。

SDImageCache(缓存类),这个类用于图片缓存。

SDImageLoader,这个类用于图片加载(主要是下载功能的核心SDWebImageDownloade(下载类)

UIkit拓展。一般使用都是经过这些拓展来使用。方便直接使用SD的功能。

在通过UIkit的拓展类使用SD加载图片的时候,其实是通过SDWebImageManager类调用了缓存类与下载类经过一定的流程,才把图片显示到手机上。下面就图片显示简单的描述一下这个流程:


image.png

上图的标红已经把大致的流程显示的很清楚。下面详细的描述一下图片的下载流程

1.首先,无论是下载还是缓存,都分别代表一个任务。

2.SD在执行下载或者缓存的时候,都会把对应的任务封装到operation里:


image.png

3.SD会把所有的operation封装到一个全局的字典里,这个字段是、NSMapTable

image.png

4.在所有操作之前,先判断这个View上有没有在执行任务,如果有就把即将开始的任务取消。没有就下一步


image.png

5.SD会调用管理类的loadImage方法。有缓存就加载缓存,没缓存就网络获取。


image.png

6.当图片已经下载完毕或者从缓存中获取到之后,有两个选择:

SD的缓存原理
SD的缓存由内存缓存和磁盘缓存同时控制。

image.png

1.配置类

image.png
shouldDecompressImages这个属性负责图片的压缩,但压缩的过程会消耗一定的内存,如果图片过大,会造成内存爆针。这时候只要把这个属性置位不压缩就可以了。 image.png
shouldCacheImagesInmemory这个值是是否需要在内存中做缓存。
  1. 缓存类
    image.png

2.1 内存缓存
缓存类首先定义了一个内存缓存的对象。

image.png
image.png

这是一个继承于系统的NSCache的对象,并定义了一个NSMapTable的弱缓存表。

与Dictionary相比,NSMapTable拥有更多的内存语义,如copy,assign,strong。

在用dic使用一个类(如NSString)作为key进行setValueForKey的时候,这个类就必须要实现NScopy协议。但是实现了这个协议后在setValueForKey时,dic会默认把这个类copy一下。这就会导致我们实际存储的东西跟想要存储的东西,不是同一个内存地址,也就是不是同一个东西。

而NSMapTable拥有更多的内存语义。如weak,strong。可以参见SD对于这个weakCache的初始化:

image.png
可以看到,这个NSMapTable把key做了强引用,把value做了弱引用。好处就是,因为不再有nscopy协议,保证这个了key,value一定就是我们传过来的key,value。而且还因为放在了全局的弱引用表中,当我们的对象(这个对象表示图片的内存)被释放之后,这个value也会就会被NSMapTable释放,而且由于value释放了,key也会被释放。这样既不用担心key不是我们想要存储的key,也不会担心key或者value无法释放。最主要的是,使用了NSMapTable后,就能手动管理要存储的图片内存的释放。}

不使用系统Cache因为NSCahe类的缓存释放时间完全由系统管理,我们无法得知NSCahe缓存的释放时间,这样可能在我们需要这个缓存的时候,系统却已经把这个缓存给释放了。所以SD继承于NSCahe后,又重新做了一个若缓存表,用来在需要某个缓存的时候,确定这个缓存不会被释放。

缓存机制的实现

不难看出多占用一份内存的好处,用内存空间换取了查询时间。保证了尽量高效查询的同时,又保证了数据一定不被释放。

2.2 磁盘缓存
磁盘缓存,首先会创建一个缓存目录

image.png
然后把文件的key值进行MD5加密,再经过一些组合,最终得到文件名:
image.png

SD两种缓存的结合

image.png
首先执行缓存操作的,是我们的管理类。执行方法是loadImageWithURL
内部如下,核心标红
image.png

5个重点。无论是存磁盘还是存硬盘,存的Data都是二进制数据。
标点1:是从缓存中查找图片。

标点2:因为从磁盘中查找比较耗时,为了确定操作安全,新建一个opration对象,并把加入全局的字段中,如果发生一个空间在图片未加载完全时就又加载了一次这张图片,则直接需要再次加载的操作。

标点3:自动释放池,当一个快代码会产生大量临时变量时,为了能让这些临时变量用完立马就释放,就需要给这些变量加入自动释放池中。又因为整个APP代码就是在一个自动释放池中,这一块就算不加这个释放池也没关系。但是释放的时机会慢不少,无法最快速度的回收内存。

标点4:根据key找出2进制数据。

标点5:拿到数据后,再存一份到内存中。这样下次再查的时候,就能最快的查找到。

上一篇下一篇

猜你喜欢

热点阅读