(0044) iOS 开发之SDWebImage 深度学习其源码和原理

来源:互联网 发布:知乎平均学历 编辑:程序博客网 时间:2024/05/22 02:28

闲着没事看了SDWebImage的源码。清晰了它的原理。

SDWebImage 深度学习

1.它是iOS图片加载框架

它支持从网络中下载且缓存图片,并设置图片到对应的UIImageView控件或者UIButton控件。在项目中使用SDWebImage来管理图片加载相关操作可以极大地提高开发效率,让我们更加专注于业务逻辑实现。


实现原理:其实SDWebImage之所以能够实现缓存的原理关键就是在哪个key值。

- (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)urlandPlaceholderImage:(UIImage *)placeholderoptions:(SDWebImageOptions)optionsprogress:(SDWebImageDownloaderProgressBlock)progressBlockcompleted:(SDWebImageCompletionBlock)completedBlock;

比如使用它的时候,其实就是把url当做了一个图片的key值,然后存储对应的图片,如果下次请求的url和这次请求的url一样,那么就直接根据url(这个key)来取图片,如果url作为key的图片缓存不存在,就去请求远程服务器,然后请求过来之后再次将url和图片对应,然后存储。


2.SDWebImage 概论

1.提供了一个UIImageViewcategory用来加载网络图片并且对网络图片的缓存进行管理

2.采用异步方式来下载网络图片

3.采用异步方式,使用memorydisk来缓存网络图片,自动管理缓存。

4.支持GIF动画

5.支持WebP格式

6.同一个URL的网络图片不会被重复下载

7.失效的URL不会被无限重试

8.耗时操作都在子线程,确保不会阻塞主线程

9.使用GCDARC


注意:SDWebImage 使用NSOperationQueue 线程队列来处理多线程。耗时操作都是在子线程里处理。

_downloadQueue = [NSOperationQueuenew];

_downloadQueue.maxConcurrentOperationCount =6;

最大maxConcurrentOperationCount  最大并发队列为6.


/********************************************************************/

一、options所有选项:

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

  //失败后重试

     SDWebImageRetryFailed = 1 << 0,

      

     //UI交互期间开始下载,导致延迟下载比如UIScrollView减速。

     SDWebImageLowPriority = 1 << 1,

      

     //只进行内存缓存

     SDWebImageCacheMemoryOnly = 1 << 2,

      

     //这个标志可以渐进式下载,显示的图像是逐步在下载

     SDWebImageProgressiveDownload = 1 << 3,

      

     //刷新缓存

     SDWebImageRefreshCached = 1 << 4,

      

     //后台下载

     SDWebImageContinueInBackground = 1 << 5,

      

     //NSMutableURLRequest.HTTPShouldHandleCookies = YES;

      

     SDWebImageHandleCookies = 1 << 6,

      

     //允许使用无效的SSL证书

     //SDWebImageAllowInvalidSSLCertificates = 1 << 7,

      

     //优先下载

     SDWebImageHighPriority = 1 << 8,

      

     //延迟占位符

     SDWebImageDelayPlaceholder = 1 << 9,

      

     //改变动画形象

     SDWebImageTransformAnimatedImage = 1 << 10,


/********************************************************************/

UIImageView+WebCache.h

1. UIImageViewcategory,来添加新的方法。


/* Set the imageView `image` with an `url`,The download is asynchronous and cached.*/

2.- (void)sd_setImageWithURL:(NSURL *)url;


/*@param placeholder The image to be set initially, until the image request finishes.*/

3.- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;


/*@param options 主要看SDWebImageOptions的枚举*/

4.- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;


/*completedBlock A block called when operation has been completed*/

5.- (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock;


/*同上,只是多了placeholderImage*/

6.- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;


/*同上,只是多了SDWebImageOptions枚举*/

7.- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;


/*同上,只是多了progress*/

8.- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;


/*PreviousCached*/

9.- (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;


/*以用一组图片生成动画:*/

10.- (void)sd_setAnimationImagesWithURLs:(NSArray *)arrayOfURLs;


11./*Cancel the current download*/

- (void)sd_cancelCurrentImageLoad;

- (void)sd_cancelCurrentAnimationImagesLoad;


/*Show activity UIActivityIndicatorView  菊花显示*/

12.- (void)setShowActivityIndicatorView:(BOOL)show;


/*@param style The style of the UIActivityIndicatorView 菊花样式*/

13.- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style;

pod 'UIActivityIndicator-for-SDWebImage' 一个帮助使用SDWebImage带有UIActivityIndicatorpod



读.m   (使用了objc/runtime.h

主要有三点:

1. 先移除已有的operationsd_cancelImageLoadOperationWithKey

2.帮助imageView添加UIActivityIndicatorView操作。

3.使用SDWebImageManager类下载url,并返回相应的block,同时把这个下载operation添加到operationDictionary队列中。


/********************************************************************/

UIButton+WebCache.h

//  UIButton加载图片

/*UIImageView不同的是多了UIControlState*/

1.- (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;


/*设置BackgroundImage*/

2.- (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;


3.其他的一些方法都是这两个的子集,不在介绍。


读.m   跟UIImageView+WebCache的.m 基本一样。

/********************************************************************/


UIImage+GIF.h 这个类别就是让UIImageView能显示gif 的类别。


/*通过这个方法加载gif*/

1.+ (UIImage *)sd_animatedGIFNamed:(NSString *)name;


主要学习到:加载gif 的原理 实质是一定时间内加载多个image。

1.将gif 文件读取后,转化为data 类型

2.data 转化为CGImageSourceRef,可以获取组成gifimage的个数。

3.然后重新转化为data-> image 

    4.利用UIImage的动画属性设置即可:[UIImageanimatedImageWithImages:imagesduration:duration];


/********************************************************************/


UIImage+MultiFormat.h 这个类别就是能加载:多种类型的图片格式png,gif,tiffjpeg.

1.+ (UIImage *)sd_imageWithData:(NSData *)data;



NSData+ImageContentType.h   这个类别是判断图片 data  的类型png,gif,tiffjpeg等。

1.+ (NSString *)sd_contentTypeForImageData:(NSData *)data;


UIView+WebCacheOperation.h这个类别是作为父类的为子类(UIImageViewUIButton)提供服务的

/*存储operation 到字典、取消operation、移除operation*/

- (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key;

- (void)sd_cancelImageLoadOperationWithKey:(NSString *)key;

- (void)sd_removeImageLoadOperationWithKey:(NSString *)key;


UIImageView+HighlightedWebCache.h  这个类别是设置UIImageView高亮状态下的image 。

 方法和UIImageView+WebCache 一致。



/********************************************************************/

类别看完了,下面是真正SDWebImage 帮我们实现url下载,缓存的类。

核心类

SDWebImageManager.h  是个单例类

/*Returns global SDWebImageManager instance. */

@property (strong,nonatomic,readonly)SDImageCache *imageCache;

@property (strong,nonatomic,readonly)SDWebImageDownloader *imageDownloader;


1.+ (SDWebImageManager *)sharedManager;


/*初始化带有上面两个属性的实例化。*/

2.- (instancetype)initWithCache:(SDImageCache *)cache downloader:(SDWebImageDownloader *)downloader;


/*

SDWebImage 第三方库的核心方法

如果在缓存中不存在,则在给定URL处下载图像,否则返回缓存版本。

@param url            The URL to the image

@param options       SDWebImageOptions

@param progressBlock  SDWebImageDownloaderProgressBlock

@param completedBlock SDWebImageCompletionWithFinishedBlock

 */

3.- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock

 completed:(SDWebImageCompletionWithFinishedBlock)completedBlock;


实现过程

1.加锁访问:判断url是否在failedURLs数组中。如果存在则不在持续请求。直接返回失败block

2.加锁访问:将operation操作对象添加到已存在的runningOperations队列数组。

3. 根据url去缓存中去取keyNSString *key = [self cacheKeyForURL:url];

4.第一步:先去内存(Memory高速缓存中去取,有则返回image 和CacheType 类型。

    UIImage *image = [selfimageFromMemoryCacheForKey:key];

    doneBlock(image, SDImageCacheTypeMemory);

  第二步:没有继续去磁盘(Disk)高速缓存中去,有则先写入Memory,如空间不足,通过添加通知UIApplicationDidReceiveMemoryWarningNotification得知内存警告,清空缓存。然后返回Disk中的image 和CacheType 类型。

UIImage *diskImage = [selfdiskImageForKey:key];

if (diskImage &&self.shouldCacheImagesInMemory) {

NSUInteger cost =SDCacheCostForImage(diskImage);

[self.memCachesetObject:diskImageforKey:keycost:cost];

    }

doneBlock(diskImage, SDImageCacheTypeDisk);

    第三步:如果前者仍没有找到,说明所有缓存都不存在该图片,需要下载图片。SDWebImageDownloader类去处理下载使用NSMutableURLRequest使用NSURLSession发起请求SDWebImageDownloaderOperation这个类专门封装NSURLSession请求,并实现NSURLSessionDataDelegate代理,处理接受数据回调。整个url下载完成。


/********************************************************************/

主要类

SDWebImageDownloader.h

发起http请求下载类,NSURLSession发请求,和实现代理。


SDWebImageDownloaderOperation.h

SDWebImageDownloader数据回调到本类中。


SDImageCache.h

缓存处理对象,存储store,取query,删除remove,清除clear等的操作。


我们可以使用它做本地缓存:

很多时候我们可能拍照得到的一张图片要多个地方使用,那么我们就希望可以把这张图片放到缓存里面,然后每次用这张图片的时候就去通过特定的方式取即可。SDWebImage就有这样的一个类:SDImageCache。该类完美地帮助了我们解决了这个问题。

存图片:

SDImageCache *imageCache = [SDImageCache sharedImageCache];

   [imageCache storeImage:imageforKey:@"myphoto"toDisk:YES];

取图片:

SDImageCache *imageCache = [SDImageCache sharedImageCache];

    UIImage *image = [imageCache imageFromDiskCacheForKey:@"myphoto"];


其他类

SDWebImageDecoder.h

强制解压缩类 ForceDecode 


SDWebImageCompat.h

转换2x,3ximage


SDWebImagePrefetcher.h

预取供将来使用缓存中的某些 Url。在低优先级中下载图像。


// Url 在同一时间预取的最大数目。默认值为 3。

@property (nonatomic, assign) NSUInteger maxConcurrentDownloads


// Prefetcher 的 SDWebImageOptions。默认值为 SDWebImageLowPriority。

@property (nonatomic, assign) SDWebImageOptions options


+ (SDWebImagePrefetcher *)sharedImagePrefetcher

/*删除和取消排队的列表*/

- (void)cancelPrefetching


/*分配让SDWebImagePrefetcher排队预取的 Url 的列表,目前一个图像,一次下载和跳过失败的下载的图像和进行到列表中的下一个图像*/

@parame url  要预取的 Url 的列表

- (void)prefetchURLs:(NSArray *)urls


/*分配让SDWebImagePrefetcher排队预取的 Url 的列表,目前一个图像,一次下载和跳过失败的下载的图像和进行到列表中的下一个图像 */

@parame url要预取的 Url 的列表

@parame completionBlock 为预取完毕的回调

- (void)prefetchURLs:(NSArray *)urls completed:(void ( ^ ) ( NSUInteger finishedCount , NSUInteger skippedCount ))completionBlock 


/********************************************************************/



参考:http://www.cocoachina.com/ios/20141212/10622.html

http://www.tuicool.com/articles/rA3IryE

http://blog.csdn.net/ios_apple/article/details/24310719

1 0
原创粉丝点击