在开发项目的过程中会用到很多第三方库,比如AFNetWorking,SDWebImage,FMDB等,但一直都没去好好的研究一下,最近刚好项目不是太紧,闲下来可以给自己充充电,先研究一下SDWebImage的底层实现,源码地址:SDWebImage
先介绍一下SDWebImage,我们使用较多的是它提供的UIImageView分类,支持从远程服务器下载并缓存图片。自从iOS5.0开始,NSURLCache也可以处理磁盘缓存,那么SDWebImage的优势在哪?首先NSURLCache是缓存原始数据(raw data)到磁盘或内存,因此每次使用的时候需要将原始数据转换成具体的对象,如UIImage等,这会导致额外的数据解析以及内存占用等,而SDWebImage则是缓存UIImage对象在内存,缓存在NSCache中,同时直接保存压缩过的图片到磁盘中;还有一个问题是当你第一次在UIImageView中使用image对象的时候,图片的解码是在主线程中运行的!而SDWebImage会强制将解码操作放到子线程中。下图是SDWebImage简单的类图关系:
下面从UIImageView的图片加载开始看起,Let’s go!
首先我们在给UIImageView设置图片的时候会调用方法:
1 |
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder; |
其中url为远程图片的地址,而placeholder为预显示的图片。
其实还可以添加一些额外的参数,比如图片选项SDWebImageOptions
1 2 |
typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) { SDWebImageRetryFailed = 1 |
一般使用的是SDWebImageRetryFailed | SDWebImageLowPriority,下面看看具体的函数调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
- (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);//关联该view对应的图片URL /*...*/ if (url) { __weak UIImageView *wself = self;//防止retain cricle //由SDWebImageManager负责图片的获取 id 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"]; } } |
可以看出图片是从服务端、内存或者硬盘获取是由SDWebImageManager管理的,这个类有几个重要的属性:
1 2 3 |
@property (strong, nonatomic, readwrite) SDImageCache imageCache;//负责管理cache,涉及内存缓存和硬盘保存 @property (strong, nonatomic, readwrite) SDWebImageDownloader imageDownloader;//负责从网络下载图片 @property (strong, nonatomic) NSMutableArray *runningOperations;//包含所有当前正在下载的操作对象 |
manager会根据URL先去imageCache中查找对应的图片,如果没有在使用downloader去下载,并在下载完成缓存图片到imageCache,接着看实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
- (id )downloadImageWithURL:(NSURL *thub.com/rs/SDWebImage" target="_blank">SDWebImage 先介绍一下SDWebImage,我们使用较多的是它提供的UIImageView分类,支持从远程服务器下载并缓存图片。自从iOS5.0开始,NSURLCache也可以处理磁盘缓存,那么SDWebImage的优势在哪?首先NSURLCache是缓存原始数据(raw data)到磁盘或内存,因此每次使用的时候需要将原始数据转换成具体的对象,如UIImage等,这会导致额外的数据解析以及内存占用等,而SDWebImage则是缓存UIImage对象在内存,缓存在NSCache中,同时直接保存压缩过的图片到磁盘中;还有一个问题是当你第一次在UIImageView中使用image对象的时候,图片的解码是在主线程中运行的!而SDWebImage会强制将解码操作放到子线程中。下图是SDWebImage简单的类图关系: 下面从UIImageView的图片加载开始看起,Let’s go! 首先我们在给UIImageView设置图片的时候会调用方法:
其中url为远程图片的地址,而placeholder为预显示的图片。
一般使用的是SDWebImageRetryFailed | SDWebImageLowPriority,下面看看具体的函数调用:
可以看出图片是从服务端、内存或者硬盘获取是由SDWebImageManager管理的,这个类有几个重要的属性:
manager会根据URL先去imageCache中查找对应的图片,如果没有在使用downloader去下载,并在下载完成缓存图片到imageCache,接着看实现:
|