SDWebImage-图片缓存

图片缓存是SDWebImage最重要,最常用的功能。用户浏览过的图片会默认缓存在cache与磁盘上,缓存默认保存一星期时间。也就是说在无网络的环境下,用户依然能够通过缓存查看到一星期之内的已经浏览过的图片。很强大,但是它也是个吃磁盘的怪物,一张图片数据实际上会在磁盘上保存两份,可以想象磁盘可用空间减小的速度有多快。建议使用SDWebImage的开发者给用户提供一个清除缓存的功能,使用户能够及时的清理磁盘,避免App被卸载的悲剧。

SDWebImageManager

SDWebImageManager类是SDWebImage的核心类,它管理着图片的下一步具体行为:

  • 从缓存中查找图片
  • 图片存在,显示图片
  • 图片不存在,下载图片
  • 下载完成后,将图片添加到缓存,显示图片

在这个类中,将图片缓存功能与上一章所说的图片下载功能关联到了一起,构成了SDWebImage的主体图片显示逻辑。

SDImageCache

图片缓存的代码主体类是SDImagaCache,毫无疑问该类的主要代码逻辑就是增、删、查、改等操作。这里我们重点来看下面这几个关键点:

图片标识

缓存图片首先要解决的问题就是通过什么来区分一张张的图片,我们自然而然的会想到图片的URL链接。是的,SDWebImage也是这样干的:


SDWebImage-图片缓存_第1张图片
SDWebImageManager获得图片缓存使用的key

SDWebImage-图片缓存_第2张图片
SDImageCache保存图片到磁盘使用的名称

与我们设想不同的一点是,它会到图片的URL作MD5运算得到新的文件名,使用该名称来保存图片,避免URL名称过长导致异常。

查询缓存图片

先从cache中查找图片,没有找到再尝试从磁盘中查找。

UIImage* = [self imageFromMemoryCacheForKey:key];
if(image){
  doneBlock(image, SDImageCacheTypeMemory);
  return nil;
}

从磁盘中查找时使用了多线程,因此整个查找方法的返回会为一个NSOperation对象。

NSOperation* operation = [NSOperation new];
dispatch_async(self.ioQueue, ^{
  if(operation.isCancelled){
    return;
  }
  @autoreleasepool{
    UIImage* diskImage = [self diskImageForKey:key];
    if(diskImage && self.shouldCacheImagesInMemory){
      NSUInteger cost = SDCacheCostForImage(diskImage);
      [self.memCache setObject:diskImage forKey:key cost:cost];
    }
    dispatch_async(dispatch_get_main_queue(), ^{
      doneBlock(diskImage, SDImageCacheTypeDisk);
    });
  }
});
return operation;

这里要注意的一点是,ioQueue是一个serial queue,所有对磁盘缓存图片的增、删、改、查操作都被放到这个队列中排队,保证了多线程操作的安全。

吐嘈

不是太喜欢整个工程里全是Block的代码风格,这让我感觉到恐慌。而在OC里面,一但一个环节使用了Block,其后所有环节可能都需要使用,且基本都是在前一环节Block的基础上的进一步封装,很容易就让阅读者陷入困境。有什么好的方案能改进这种情形吗?

你可能感兴趣的:(SDWebImage-图片缓存)