美文网首页
SDWebImage实现原理

SDWebImage实现原理

作者: Foxhoundsun | 来源:发表于2020-04-28 22:03 被阅读0次

概念总成

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.当图片已经下载完毕或者从缓存中获取到之后,有两个选择:

  • 1.如果不需要设置图片就直接把图片返回给当前的View,并标记当前界面需要刷新。这样runloop在下一个周期,就会刷新view显示图片。
  • 2.如果需要设置这张图片(如加水印之类的处理)则把图片通过block返回给当前方法的调用者,并在调用者处理完成图片之后,再标记刷新。


    image.png

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后,又重新做了一个若缓存表,用来在需要某个缓存的时候,确定这个缓存不会被释放。

缓存机制的实现

    1. SDMemoryCache重写了NSCache的核心方法:


      image.png

      虽然重写,但是还是调用super方法。通过NSCache的声明文件可发现。NSCache一定在实现的时候有个key与value对应的表没有暴露出来(这个表可能是字段也可能是数组,但是一定存在。因为如果不存在就不可能存的住keyvalue)。这就意味着系统的管理缓存释放,其实就是对这个表的管理。所以在给NSMapTable做setKeyvalue操作的时候,我们先把数据存一份在系统管理的表中,再存一份到我们自己管理的表中(就是刚才的weakCache)。但是这样做却多占用了一份内存。


      image.png
    1. 取值方法步骤分为3步:
      1.直接在系统的NSCache里查找,因为NSCache的释放完全由系统管理,所以取值的时候很可能value已经被系统释放。

    2.如果已经被系统释放,就先从我们自己建的表中取出这个value,这样保证了每次取value的时候,就算NSCache的那一份已经释放,自己存的还能拿出来用。

    3.如果取出了value,首先要再调用一次NSCache的存储,把这个value存到NSCache中。保证了NSCache中尽可能的拥有这份value,这样在下次再取值的时候,如果NSCache中的value没有被释放,就能直接拿来用。

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

    1. SD还监听了didReceiveMemoryWarning方法


      image.png

      一旦出现内存警告,SD会立即释放已占用的内存。保证了就算SD存储了两份内存,当出现内存警告时,不会造成APP闪退。

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:拿到数据后,再存一份到内存中。这样下次再查的时候,就能最快的查找到。

相关文章

网友评论

      本文标题:SDWebImage实现原理

      本文链接:https://www.haomeiwen.com/subject/bqgbwhtx.html