SDWebImage浅析

作者: 码蚁居然被用过了 | 来源:发表于2016-04-17 23:55 被阅读385次

最近几个项目在使用到图片的时候都采取异步加载的情况,然而原生的ImageView的相关方式是同步执行的,如果图片太大或者网络条件不佳,那么就会造成主界面卡死。所以我们最后才用的是SDWebImage这个库。像往常一样,我们还是来简单分析一下SD都做了哪些事情。

SD的源码大致可分为两部分,功能类和Category,功能类包含如下文件,我们来一个个地分析。

Paste_Image.png

SDImageCache负责管理图片的缓存,包括使用NSCache实现内存缓存以及使用NSFileManger实现磁盘缓存,对外提供了配置参数、存储/删除/查询图片缓存的方法。

SDWebImageCompat负责对Image进行缩放处理,以兼容2x/3x。这里有一个细节需要注意:

inline UIImage *SDScaledImageForKey(NSString *key, UIImage *image)

方式用了inline进行了修饰,inline的好处是对于需要频繁调用的方法,可以提高运行效率。具体可参见这里。于是我按照博客上的例子试了试,看了一下汇编的代码,发现并没有call与不call的区别,都是"bl _add",于是又Google了一下,发现了这个
这里面提到即使使用inline,编译器也不一定就这么做,最终决定权在编译器,代码里的声明只是建议。而且现在CPU速度很快,递归栈的速度也基本忽略不计了,对效率的影响并不大。

SDWebImageDecoder负责图片的解码。这里有个点,即通过 imageNamed 创建 UIImage 时,系统实际上只是把这个文件名放到 UIImage 里返回,并没有进行实际的文件读取和解码。当 UIImage 第一次显示到屏幕上时,其内部的解码方法才会被调用。这样带来的结果就是对于特别大的图,在显示的时候会出现延迟。

SDWebImageDownloader负责图片的下载。包括设置是否解码、并发量、使用NSOperationQueue管理请求等。

SDWebImageDownloaderOperation继承NSOperation,处理业务层传递来的回调事件。

SDWebImageManager负责对业务层提供下载图片、缓存图片、检查图片是否存在等方法。

SDWebImagePrefetcher可以预下载图片,方便以后使用,个人理解就是比直接用Manager预加载更方便一点,因为作者已经把相关的代码封装好了。

下面以最常用的[UIImageView sd_setImageWithURL]方法为例,分析一下SD的大致流程:
1)取消之前的请求;

[self sd_cancelCurrentImageLoad];

2)设置占位图;

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

3)通过SDWebImageManager处理下载逻辑,并将此次加载图片的请求保存,以便cancel;

id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
            //......
            });
        }];
        [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];

4)检查image是否在内存中存在;

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

5)检查image在磁盘中是否存在;

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);
            });
        }
    });

6)通过imageDownloader下载图片;

id <SDWebImageOperation> subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished)

7)在内存和磁盘中保存image;

[self.imageCache storeImage:transformedImage recalculateFromImage:imageWasTransformed imageData:(imageWasTransformed ? nil : data) forKey:key toDisk:cacheOnDisk];

8)处理业务层的回调;

completedBlock(transformedImage, nil, SDImageCacheTypeNone, finished, url);

相关文章

  • SDWebImage浅析

    最近几个项目在使用到图片的时候都采取异步加载的情况,然而原生的ImageView的相关方式是同步执行的,如果图片太...

  • SDWebImage浅析

    SDWebImage特征 提供了UIImageView,UIButton,MKAnnotationView的cat...

  • SDWebImage 源码浅析

    图片下载     在SDWebImage中,图片的下载是由SDWebImageDownloader完成的。SDWe...

  • SDWebImage原理浅析

    遇见你之前,我只有眼前的苟且,遇见你之后,才有了诗和远方。 话不多说,我们最熟悉的sd_setImageWithU...

  • SDWebImage源码浅析

    1、平时开发的过程中用到过三方库吗?2、使用三方库的过程中遇到过什么问题吗?3、有读过优秀三方的源码么?4、知道三...

  • 源码浅析 SDWebImage 5.6

    本文基于 SDWebImage 5.6。重读的原因也是由于发现它的 API 在不断迭代,许多结构已经不同与早期版本...

  • iOS中SDWebImage框架浅析

    下载图片并显示 下载图片并计算下载进度 使用SDWebImageManager单例下载 同时做内存缓存和图片缓存可...

  • iOS开发-SDWebImage框架浅析

    一、第三方框架SDWebImage (1)SDWebImage基本使用 (2)SDWebImage内部结构 )

  • 网络(七):SDWebImage源码浅析

    目录一、我们先自己写一个加载网络图片的demo 1、最简单的实现 2、图片缓存处理:增加内存缓存 3、图片缓存处理...

  • iOS开发:关于SDWebImage源码浅析

    一、下载Demo后运行报错 1、no such file or directory:······libwebp··...

网友评论

    本文标题:SDWebImage浅析

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