SDWebImage源码解析(二)

上一篇:SDWebImage源码解析(一)


2、缓存

为了减少网络流量的消耗,我们都希望下载下来的图片缓存到本地,下次再去获取同一张图片时,可以直接从本地获取,而不再从远程服务器获取。这样做的另一个好处是提升了用户体验,用户第二次查看同一幅图片时,能快速从本地获取图片直接呈现给用户。

SDWebImage提供了对图片缓存的支持,而该功能是由SDImageCache类来完成的。该类负责处理内存缓存及一个可选的磁盘缓存。其中磁盘缓存的写操作是异步的,这样就不会对UI操作造成影响。


2.1 内存缓存及磁盘缓存

内存缓存的处理是使用NSCache对象来实现的。NSCache是一个类似于集合的容器。它存储key-value对,这一点类似于NSDictionary类。我们通常使用缓存来临时存储短时间使用但创建昂贵的对象。重用这些对象可以优化性能,因为它们的值不需要重新计算。另外一方面,这些对象对于程序来说不是紧要的,在内存紧张时会被丢弃。

磁盘缓存的处理则是使用NSFileManager对象来实现的。图片存储的位置是位于Cache文件夹。另外,SDImageCache还定义了一个串行队列,来异步存储图片。

内存缓存与磁盘缓存相关变量的声明及定义如下:

@interface SDImageCache ()
@property (strong, nonatomic) NSCache *memCache;
@property (strong, nonatomic) NSString *diskCachePath;
@property (strong, nonatomic) NSMutableArray *customPaths;
@property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t ioQueue;
@end
- (id)initWithNamespace:(NSString *)ns {
    if ((self = [super init])) {
  NSString *fullNamespace = [@"com.hackemist.SDWebImageCache." stringByAppendingString:ns];
  ...
  _ioQueue = dispatch_queue_create("com.hackemist.SDWebImageCache", DISPATCH_QUEUE_SERIAL);
  ...
  // 初始化内存缓存
  _memCache = [[NSCache alloc] init];
  _memCache.name = fullNamespace;
  // 初始化磁盘缓存
  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
  _diskCachePath = [paths[0] stringByAppendingPathComponent:fullNamespace];
  dispatch_sync(_ioQueue, ^{
      _fileManager = [NSFileManager new];
  });
  ...
    }
    return self;
}

SDImageCache提供了大量方法来缓存、获取、移除及清空图片。而对于每个图片,为了方便地在内存或磁盘中对它进行这些操作,我们需要一个key值来索引它。

在内存中,我们将其作为NSCache的key值,而在磁盘中,我们用这个key作为图片的文件名。对于一个远程服务器下载的图片,其url是作为这个key的最佳选择了。我们在后面会看到这个key值的重要性。


2.2 存储图片

我们先来看看图片的缓存操作,当下载完图片后,会先将图片保存到NSCache中,并把图片像素大小作为该对象的cost值,同时如果需要保存到硬盘,会先判断图片的格式,PNG或者JPEG,并保存对应的NSData到缓存路径中,文件名为URL的MD5值:

- (NSString *)cachedFileNameForKey:(NSString *)key {
    //根据key生成对应的MD5值作为文件名
    const char *str = [key UTF8String];
    if (str == NULL) {
        str = "";
    }
    unsigned char r[CC_MD5_DIGEST_LENGTH];
    CC_MD5(str, (CC_LONG)strlen(str), r);
    NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                                                    r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]];

    return filename;
}<
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值