SDWebImage-图片缓存

作者: 秦砖 | 来源:发表于2017-01-20 15:10 被阅读259次

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

    SDWebImageManager

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

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

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

    SDImageCache

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

    图片标识

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


    SDWebImageManager获得图片缓存使用的key
    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-图片缓存

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