SDWebImage实现原理

1、类图
SDWebImageClassDiagram.png
2、时序图
SDWebImageSequenceDiagram.png
3、目录结构
Downloader
  • SDWebImageDownloader 下载图片优化图片加载
  • SDWebImageDownloaderOperation 继承NSOperation,用来处理下载任务的
Cache
  • SDImageCache 用来处理内存缓存和磁盘缓存的,其中磁盘缓存是异步进行的,不会阻塞主线程
Utils
  • SDWebImageManager 将图片下载(SDWebImageDownloader)和图片缓存(SDImageCache)两个独立的功能组合起来
  • SDWebImageDecoder 图片解码器,用于图片下载完成后进行解码
  • SDWebImagePrefetcher 预下载图片
Categories
  • UIView+WebCacheOperation 用来记录图片加载的operation,方便需要时取消和移除图片加载的operation
  • UIImageView+WebCache 集成SDWebImageManager的图片下载和缓存功能到UIImage的方法中,方便使用
  • UIImageView+HighlightedWebCache
  • UIButton +WebCache
  • NSData+ImageContentType 用于获取图片数据的格式(jpeg png等)
  • UIImage+GIF 用于加载GIF动图
  • UIImage+MultiFormat 根据不同格式的二进制数据转成UIImage对象
Other
  • SDWebImageOperation 协议 只有一个方法cancel
  • SDWebImageCompat 宏定义、常量、通用函数
4、流程
[imageView sd_setImageWithURL:url placeholderImage:placeholderImage]
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock {
    [self sd_cancelCurrentImageLoad];
    objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    if (!(options & SDWebImageDelayPlaceholder)) {
        dispatch_main_async_safe(^{
            self.image = placeholder;
        });
    }
    
    if (url) {

        // check if activityView is enabled or not
        if ([self showActivityIndicatorView]) {
            [self addActivityIndicator];
        }

        __weak __typeof(self)wself = self;
        id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
            [wself removeActivityIndicator];
            if (!wself) return;
            dispatch_main_sync_safe(^{
                if (!wself) return;
                if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock)
                {
                    completedBlock(image, error, cacheType, url);
                    return;
                }
                else if (image) {
                    wself.image = image;
                    [wself setNeedsLayout];
                } else {
                    if ((options & SDWebImageDelayPlaceholder)) {
                        wself.image = placeholder;
                        [wself setNeedsLayout];
                    }
                }
                if (completedBlock && finished) {
                    completedBlock(image, error, cacheType, url);
                }
            });
        }];
        [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
    } else {
        dispatch_main_async_safe(^{
            [self removeActivityIndicator];
            if (completedBlock) {
                NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
                completedBlock(nil, error, SDImageCacheTypeNone, url);
            }
        });
    }
}

经过层层调用,直到 UIImageView+WebCache 中最核心的方法 sd_setImageWithURL: placeholderImage: options: progress: completed: 该方法中,主要做了以下几件事:

  1. [self sd_cancelCurrentImageLoad];取消当前正在进行的加载任务operation
  2. self.image = placeholder;设置placeholder
  3. 如果url不为nil,就通过SDWebImageManager单例开启图片加载任务operation,SDWebImageManager的图片加载方法中会返回一个SDWebImageCombineOperation对象,这个对象包含一个cacheOperation和一个cancelBlock。

SDWebImageManager 的图片加载方法 downloadImageWithURL:options:progress:completed: 中

  1. 会先拿图片缓存的 key (这个 key 默认是图片 URL)去 SDImageCache 中读取内存缓存,如果有,就返回给 SDWebImageManager;
  2. 如果内存缓存没有,就开启异步线程,拿经过 MD5 处理的 key 去读取磁盘缓存,如果找到磁盘缓存了,就同步到内存缓存中去,然后再返回给 SDWebImageManager。
  3. 如果内存缓存和磁盘缓存中都没有,SDWebImageManager 就会调用 SDWebImageDownloader 单例的 -downloadImageWithURL: options: progress: completed: 方法去下载,该会先将传入的 progressBlock 和 completedBlock 保存起来,并在第一次下载该 URL 的图片时,创建一个 NSMutableURLRequest 对象和一个 SDWebImageDownloaderOperation 对象,并将该 SDWebImageDownloaderOperation 对象添加到 SDWebImageDownloader 的downloadQueue 来启动异步下载任务。

SDWebImageDownloaderOperation 中包装了一个 NSURLConnection 的网络请求,并通过 runloop 来保持 NSURLConnection 在 start 后、收到响应前不被干掉,下载图片时,监听 NSURLConnection 回调的 -connection:didReceiveData: 方法中会负责 progress 相关的处理和回调,- connectionDidFinishLoading: 方法中会负责将 data 转为 image,以及图片解码操作,并最终回调 completedBlock。
SDWebImageDownloaderOperation 中的图片下载请求完成后,会回调给 SDWebImageDownloader,然后 SDWebImageDownloader 再回调给 SDWebImageManager,SDWebImageManager 中再将图片分别缓存到内存和磁盘上(可选),并回调给 UIImageView,UIImageView 中再回到主线程设置 image 属性。至此,图片的下载和缓存操作就结束了。

SDWebImage使用LRU缓存淘汰算法。缓存有效期默认是7天。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值