深入源码理解YYCache 、SDWebImage、AFNetworking、NSCache 缓存方式与对比

深入源码理解YYCache 、SDWebImage、AFNetworking、NSCache 缓存方式与对比

转载请注明出处 http://blog.csdn.net/u014205968/article/details/78490145

在之前的一篇文章iOS缓存 NSCache详解及SDWebImage缓存策略源码分析中详细讲解了NSCache的用法以及SDWebImage内存和磁盘缓存的源码分析,本篇文章将简要讲解AFNetworking缓存类和YYCache并作出对比。

由于之前的一篇文章已经详细讲解了NSCacheSDWebImage缓存策略,本篇文章不再赘述,会简要介绍一下AFNetworkingYYCache的源码。

AFNetworking图片缓存AFAutoPurgingImageCache

AFNetworking也提供了同SDWebImage一样的下载图片的功能,也提供了缓存这些图片的功能,但它只提供了内存缓存,没有提供磁盘缓存功能。

看一下头文件:

//缓存协议,如果用户需要实现自定义的
@protocol AFImageCache <NSObject>

//添加图片并传递一个唯一id,一般使用图片的URL
- (void)addImage:(UIImage *)image withIdentifier:(NSString *)identifier;

//删除id为identifier的图片
- (BOOL)removeImageWithIdentifier:(NSString *)identifier;

//删除所有缓存图片
- (BOOL)removeAllImages;

//根据id获取图片
- (nullable UIImage *)imageWithIdentifier:(NSString *)identifier;
@end

//AFImageRequestCache协议,继承AFImageCache协议
@protocol AFImageRequestCache <AFImageCache>

//添加图片,传入下载图片的request和额外的id
- (void)addImage:(UIImage *)image forRequest:(NSURLRequest *)request withAdditionalIdentifier:(nullable NSString *)identifier;

//删除图片,传入下载图片的request和额外的id
- (BOOL)removeImageforRequest:(NSURLRequest *)request withAdditionalIdentifier:(nullable NSString *)identifier;

//根据下载图片的request和额外的id获取图片
- (nullable UIImage *)imageforRequest:(NSURLRequest *)request withAdditionalIdentifier:(nullable NSString *)identifier;

@end

//AFNetworking提供的缓存类,
@interface AFAutoPurgingImageCache : NSObject <AFImageRequestCache>

//单位是字节,能够支持最大缓存大小
@property (nonatomic, assign) UInt64 memoryCapacity;

//建议的当内存缓存要释放的时候需要释放到多大的大小
@property (nonatomic, assign) UInt64 preferredMemoryUsageAfterPurge;

//当前内存缓存占用的字节大小
@property (nonatomic, assign, readonly) UInt64 memoryUsage;

//构造函数
- (instancetype)init;

//构造函数
- (instancetype)initWithMemoryCapacity:(UInt64)memoryCapacity preferredMemoryCapacity:(UInt64)preferredMemoryCapacity;

@end

从头文件可以看出,AFNetworking提供的AFAutoPurgingImageCache接口不多,而且都很简单,只实现了内存缓存的功能。

看一下实现文件:

//缓存对象包装类
@interface AFCachedImage : NSObject
//缓存的图片
@property (nonatomic, strong) UIImage *image;
//id
@property (nonatomic, strong) NSString *identifier;
//图片字节大小
@property (nonatomic, assign) UInt64 totalBytes;
//淘汰算法是LRU所以需要记录上次访问时间
@property (nonatomic, strong) NSDate *lastAccessDate;
//没用到的属性
@property (nonatomic, assign) UInt64 currentMemoryUsage;

@end

@implementation AFCachedImage
//初始化构函数
-(instancetype)initWithImage:(UIImage *)image identifier:(NSString *)identifier {
    if (self = [self init]) {
        self.image = image;
        self.identifier = identifier;
        //计算图片的字节大小,每个像素占4字节32位
        CGSize imageSize = CGSizeMake(image.size.width * image.scale, image.size.height * image.scale);
        CGFloat bytesPerPixel = 4.0;
        CGFloat bytesPerSize = imageSize.width * imageSize.height;
        self.totalBytes = (UInt64)bytesPerPixel * (UInt64)bytesPerSize;
        self.lastAccessDate = [NSDate date];
    }
    return self;
}
//通过缓存对象获取图片时要更新上次访问时间为当前时间
- (UIImage*)accessImage {
    //直接使用NSDate
    self.lastAccessDate = [NSDate date];
    return self.image;
}

- (NSString *)description {
    NSString *descriptionString = [NSString stringWithFormat:@"Idenfitier: %@  lastAccessDate: %@ ", self.identifier, self.lastAccessDate];
    return descriptionString;

}

@end

//AFNetworking缓存类的猪脚
@interface AFAutoPurgingImageCache ()
//可变字典用于存储所有的缓存对象AFCachedImage对象,key为字符串类型
@property (nonatomic, strong) NSMutableDictionary <NSString* , AFCachedImage*> *cachedImages;
//当前缓存对象内存占用大小
@property (nonatomic, assign) UInt64 currentMemoryUsage;
//用于线程安全防止产生竞争条件,没有用锁
@property (nonatomic, strong) dispatch_queue_t synchronizationQueue;
@end

@implementation AFAutoPurgingImageCache

//构造函数,默认内存占用100M,每次清除缓存到60M
- (instancetype)init {
    return [self initWithMemoryCapacity:100 * 1024 * 1024 preferredMemoryCapacity:60 * 1024 * 1024];
}

//构造函数
- (instancetype)initWithMemoryCapacity:(UInt64)memoryCapacity preferredMemoryCapacity:(UInt64)preferredMemoryCapacity {
    if (self = [super init]) {
        self.memoryCapacity = memoryCapacity;
        self.preferredMemoryUsageAfterPurge = preferredMemoryCapacity;
        self.cachedImages = [[NSMutableDictionary alloc] init];
        //创建一个并行队列,但后面使用时都是在同步情况或barrier情况下,队列中的任务还是以串行执行
        //可以防止产生竞争条件,保证线程安全
        NSString *queueName = [NSString stringWithFormat:@"com.alamofire.autopurgingimagecache-%@", [[NSUUID UUID] UUIDString]];
        self.synchronizationQueue = dispatch_queue_create([queueName cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_CONCURRENT);

        //添加通知,监听收到系统的内存警告后删除所有缓存对象
        [[NSNotificationCenter defaultCenter]
         addObserver:self
         selector:@selector(removeAllImages)
         name:UIApplicationDidReceiveMemoryWarningNotification
         object:nil];

    }
    return self;
}
//析构函数,删除通知的监听
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
//memoryUsage的getter
- (UInt64)memoryUsage {
    __block UInt64 result = 0;
    dispatch_sync(self.synchronizationQueue, ^{
        result = self.currentMemoryUsage;
 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值