SDWebImage图片缓存流程

SDWebImage图片缓存流程分析

SDWebImage是一个功能很强大的缓存网络图片的框架。框架实现了异步加载网络图片、自动缓存图片数据等功能。以UIImageView加载网络图片为例,对其总体的加载图片流程做一个大致的分析。 首先使用SDWebImage先要导入#import"UIImageView+WebCache.h"文件,设置网络图片的图片地址就可以加载图片。

[objc] view plaincopyprint?

1.    NSURL*url = [NSURL URLWithString:@"http://b.hiphotos.baidu.com/imag1e03d003478ec54e736d196f9.jpg"];

2.    [imageViewsetImageWithURL:url];

NSURL *url = [NSURL URLWithString:@"http://b.hiphotos.baidu.com/imag1e03d003478ec54e736d196f9.jpg"];
[imageView setImageWithURL:url];

 

根据网络图片地址,SDWebImageManager类提供了方法downloadWithURL加载图片

[objc] view plaincopyprint?

1.    id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError*error, SDImageCacheType cacheType, BOOL finished){

2.    if(!wself) return;

3.    dispatch_main_sync_safe(^{

4.    if(!wself) return;

5.    if(image) {

6.    wself.image = image;

7.    [wself setNeedsLayout];

8.    }

9.    if(completedBlock && finished) {

10.  completedBlock(image,error, cacheType);

11.  }

12.  });

13.  }];

14.  objc_setAssociatedObject(self, &operationKey, operation,OBJC_ASSOCIATION_RETAIN_NONATOMIC);

15.  }

 id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished) {
            if (!wself) return;
            dispatch_main_sync_safe(^{
                if (!wself) return;
                if (image) {
                    wself.image = image;
                    [wself setNeedsLayout];
                }
                if (completedBlock && finished) {
                    completedBlock(image, error, cacheType);
                }
            });
        }];
        objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }

 

进入downloadWithURL方法,由SDImagerCache类提供方法queryDiskCacheForKey检查内存中是否有图片缓存,如果有图片缓存,回调block将图片数据传递给SDWebImageManger类。SDWebImageMange类回调block将图片数据传递给UIImageView+WebCache类去显示图片。

[objc] view plaincopyprint?

1.    UIImage*image = [selfimageFromMemoryCacheForKey:key];

2.    if(image) {

3.    doneBlock(image, SDImageCacheTypeMemory);

4.    return nil;

5.    }

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


如果内存中没有图片缓存,将会去磁盘中查找图片缓存。这一步操作是异步操作,如果从磁盘中读取到图片数据,将图片数据添加到内存缓存中,回调block将图片数据传递给SDWebImageManger类。 SDWebImageMange类回调block将图片数据传递给UIImageView+WebCache类去显示图片

[objc] view plaincopyprint?

1.    dispatch_async(self.ioQueue,^{

2.    if(operation.isCancelled) {

3.    return;

4.    }

5.     

6.    @autoreleasepool{

7.    UIImage*diskImage = [selfdiskImageForKey:key];

8.    if(diskImage) {

9.    CGFloat cost = diskImage.size.height *diskImage.size.width * diskImage.scale;

10.  [self.memCache setObject:diskImage forKey:key cost:cost];

11.  }

12.   

13.  dispatch_async(dispatch_get_main_queue(),^{

14.  doneBlock(diskImage,SDImageCacheTypeDisk);

15.  });

16.  }

dispatch_async(self.ioQueue, ^{
        if (operation.isCancelled) {
            return;
        }
        @autoreleasepool {
            UIImage *diskImage = [self diskImageForKey:key];
            if (diskImage) {
                CGFloat cost = diskImage.size.height * diskImage.size.width * diskImage.scale;
                [self.memCache setObject:diskImage forKey:key cost:cost];
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                doneBlock(diskImage, SDImageCacheTypeDisk);
            });
        }

 

内存和磁盘中都没有图片缓存,由SDWebImageDownloader类downloadImageWithURL方法请求网络下载图片。

[objc] view plaincopyprint?

1.    - (id<SDWebImageOperation>)downloadImageWithURL:(NSURL*)url options:(SDWebImageDownloaderOptions)options progress:(void (^)(NSInteger,NSInteger))progressBlock completed:(void (^)(UIImage *, NSData *, NSError *, BOOL))completedBlock {

2.    }

- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(void (^)(NSInteger, NSInteger))progressBlock completed:(void (^)(UIImage *, NSData *, NSError *, BOOL))completedBlock {
}

 

图片下载完成后,数据下载完成后交给 SDWebImageDecoder做图片解码处理,图片解码完成后回调给SDWebImageDownloader类,SDWebImageDownloader类,回调block将图片数据传递给SDWebImageManger类。 SDWebImageMange类回调block将图片数据传递给UIImageView+WebCache类显示图片。

图片数据会写入到内存和磁盘缓存中。图片数据写入磁盘缓存中是异步操作,避免拖慢主线程。

[objc] view plaincopyprint?

1.    - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk {

2.    if(!image || !key) {

3.    return;

4.    }

5.    [self.memCache setObject:image forKey:key cost:image.size.height * image.size.width * image.scale];

6.    if(toDisk) {

7.    dispatch_async(self.ioQueue,^{

8.    NSData*data = imageData;

9.     

10.  if (image && (recalculate ||!data)) {

11.  BOOL imageIsPng = YES;

12.  if ([imageData length]>= [kPNGSignatureData length]) {

13.  imageIsPng= ImageDataHasPNGPreffix(imageData);

14.  }

15.  if (imageIsPng) {

16.  data= UIImagePNGRepresentation(image);

17.  }

18.  else {

19.  data= UIImageJPEGRepresentation(image, (CGFloat)1.0);

20.  }

21.  data= [NSBitmapImageRep representationOfImageRepsInArray:image.representations usingType: NSJPEGFileType properties:nil];

22.  }

23.  if (data) {

24.  if (![_fileManagerfileExistsAtPath:_diskCachePath]) {

25.  [_fileManager createDirectoryAtPath:_diskCachePathwithIntermediateDirectories:YES attributes:nil error:NULL];

26.  }

27.  [_fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil];

28.  }

29.  });

30.  }

31.  }

- (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk {
    if (!image || !key) {
        return;
    }
    [self.memCache setObject:image forKey:key cost:image.size.height * image.size.width * image.scale];
    if (toDisk) {
        dispatch_async(self.ioQueue, ^{
            NSData *data = imageData;
            if (image && (recalculate || !data)) {
                BOOL imageIsPng = YES;
                if ([imageData length] >= [kPNGSignatureData length]) {
                    imageIsPng = ImageDataHasPNGPreffix(imageData);
                }
                if (imageIsPng) {
                    data = UIImagePNGRepresentation(image);
                }
                else {
                    data = UIImageJPEGRepresentation(image, (CGFloat)1.0);
                }
                data = [NSBitmapImageRep representationOfImageRepsInArray:image.representations usingType: NSJPEGFileType properties:nil];
            }
            if (data) {
                if (![_fileManager fileExistsAtPath:_diskCachePath]) {
                    [_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
                }
                [_fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil];
            }
        });
    }
}

 

总结:

1、SDWebImageManager*manager = [SDWebImageManager sharedManager];管理图片的加载,由SDImagerCache类检查内存中是否有图片缓存,或者由SDWebImageDownloader请求网络下载图片。

 

2SDImageCache类管理图片缓存,读取图片缓存和写入图片缓存。

 

3SDWebImageDownloader,根据URL向网络读取数据。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值