时间:2015-08-04 来源:

SDWebImage分析--源代码详细分析 【编程语言】

SDWebImage源代码分析 前言 关于网上的源代码分析也应该是不少的了web切图报价,不过对于这个经典的第三方图片下载缓存库的作者还是相当敬佩的.这里还是想就个人理解来分析下,web切图报价当做笔记加深理解也好.想看大概流程就好的可以看我上一篇博客:传送门:SDWebImage分析–库处理流程分析

[self.memCache setObject:diskImage forKey:key cost:cost]; 这个函数是NSCache中提供的缓存存储函数.有没有感觉很熟悉? 这让我想到KVO模式中常用到的setValue. 上述查找过程完毕返回结果后,psd转html ^{ doneBlock(diskImage, SDImageCacheTypeDisk); }); } }); 可以看到这里是先用传递过来的Key先进行内存缓存查找是否存在这个图片.如果查找成功则返回图片去显示.如果没有,web前端制作那么这里是新开一个NSOperation的串行队列去磁盘上查找(这里是把io操作用异步线程推到后台承接网页制作,这里还有个小细节就是作者在这里新建了一个自动释放池web切图报价,把查找操作放在里面,web切图报价等查找操作完成后自动销毁产生的额外数据.至于为什么要有这个必要后面再来细致研究下.追踪 [self diskImageForKey:key] 这个函数发现了它的图片存储路径函数为:

SDWebImage之中还编写了清除缓存的方法符合w3c标准,如果应用收到内存警告则会自动删除内存缓存的图片(按时间先后顺序).该库也提供了很多方法供我们去查询与删除图片缓存,符合w3c标准其机制也是大同小异网页外包接活, (CC_LONG)strlen(str), r[0], r[2], r[4], r[6], r[8], r[10], r[12], r[14], r[15]]; return filename; } 有做过安全加密之类算法的一看大概就知道这个是什么了.这就是将文件名进行MD5加密,html切图制作在信息传输方面也很广泛.对URL进行MD5转换之后就能得到一个唯一的128位长的字符串.对URL进行MD5转换有什么好处呢网页外包接活,可能你觉得每个图片的URL应该也是确定的啊,wap前端外包但每个URL的长度都不一样吧web前端制作,有的特别长也浪费空间,web前端制作我想得不是很深承接网页制作,但这样做应该也有便于统一存取的角度吧.然后接下来的工作就是如果从内存照到图片数据则返回,div前端切图返回的是一个NSData类型web切图报价,SDImageCache会先对data进行解压处理成相应的图片格式.获得图片的NSData之后这里有一个小片段具体是我还不甚理解的,web切图报价应该是涉及到图片的解压方面.

NSString *key = [self cacheKeyForURL:url]; operation.cacheOperation = [self.imageCache queryDiskCacheForKey:key done:^(UIImage *image, SDImageCacheType cacheType) 根据这个函数跳转到其实现的地方:

if (!(options & SDWebImageDelayPlaceholder)) { dispatch_main_async_safe(^{ self.image = placeholder; }); } 这里有必要看一下SDWebImageOptions这个枚举值都是什么东西,符合w3c标准我尽可能根据我很普通的英语来粗略翻译下了: typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) { //下载失败则重试,jpg或psd转html默认是当一个URL下载失败后会被加入黑名单 SDWebImageRetryFailed = 1 << 0, //只允许图片缓存在内存而不允许缓存在磁盘 SDWebImageCacheMemoryOnly = 1 << 2, //采用边下载边显示,承接网页制作默认是下载完成再一次性显示 SDWebImageProgressiveDownload = 1 << 3, //这个太长了,网站div+css大概意思就是忽略缓存 SDWebImageRefreshCached = 1 << 4, //在iOS4.0+允许应用在后台进行一些操作,符合w3c标准这个选项就是允许在后台继续下载 SDWebImageContinueInBackground = 1 << 5, //允许不受信任的SSL证书.实际情况慎用 SDWebImageAllowInvalidSSLCertificates = 1 << 7, //使用高级别的线程权限,div+css制作默认是等待当前线程完成再进行 SDWebImageHighPriority = 1 << 8, SDWebImageTransformAnimatedImage = 1 << 10, //下载完成后手动设置图片,web切图报价默认是下载完成后自动放到ImageView上 SDWebImageAvoidAutoSetImage = 1 << 11 }; 接下来的代码片:

一、UIImage + WebCache 入口: 我们根据设置Image的时候跳转代码到定义位置其实可以看到几乎所有类型的设置情况都是指向一个函数符合w3c标准, NSError *error, BOOL finished, NSURL *imageURL) 这里便是共享一个SDWebImageManager来进行图片的缓存查找或者下载了.并将这个operation加入到我们在看第一句的函数中那个可变的操作队列字典中.好的,web前端制作这里就到了最复杂的地方了承接网页制作,让我们跳转到这个manager的函数:

$(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i ').text(i)); }; $numbering.fadeIn(1700); }); }); 版权声明:本文为博主原创文章,div前端切图未经博主允许不得转载.

[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock]; 打开这个方法的定义代码:

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { [self sd_cancelCurrentImageLoad]; objc_setAssociatedObject(self, url, NSError *error, BOOL finished, error, url); return; } else if (image) { wself.image = image; [wself setNeedsLayout]; } else { if ((options & SDWebImageDelayPlaceholder)) { wself.image = placeholder; [wself setNeedsLayout]; } } if (completedBlock && finished) { completedBlock(image, cacheType, error, url); } }); } } 这里代码挺长的.所以我们就按重点来分析.第一句的[self sd_cancelCurrentImageLoad]; , nil, NO); } return; } dispatch_barrier_sync(self.barrierQueue, ^{ BOOL first = NO; if (!self.URLCallbacks[url]) { self.URLCallbacks[url] = [NSMutableArray new]; first = YES; } // Handle single download of simultaneous download request for the same URL NSMutableArray *callbacksForURL = self.URLCallbacks[url]; NSMutableDictionary *callbacks = [NSMutableDictionary new]; if (progressBlock) callbacks[kProgressCallbackKey] = [progressBlock copy]; if (completedBlock) callbacks[kCompletedCallbackKey] = [completedBlock copy]; [callbacksForURL addObject:callbacks]; self.URLCallbacks[url] = callbacksForURL; if (first) { createCallback(); } }); } URLCallbacks是一个包含每个图片多组回调信息的字典,web切图报价key是图片的URL地址符合w3c标准,value则是一个数组.由于允许多个图片同时下载,html切图制作因此可能会有多个线程同时操作URLCallbacks属性.为了保证URLCallbacks操作(添加、删除)的线程安全性网页外包接活,SDWebImageDownloader将这些操作作为一个个任务放到barrierQueue队列中.哦对了,wap前端外包上面提到的NSCache缓存存储步骤因为是线程安全的web前端制作,所以在存取查找的时候不需要进行额外的维护.

if ((!image || options & SDWebImageRefreshCached) && (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])) 即是如果上述操作都找不到缓存图片,web前端制作则通知实现了SDWebImageManagerDelegate 协议的对象根据URL进行图片下载.如果委托没有响应承接网页制作, NSData *data, BOOL finished) 进入这个函数的实现过程可以看到一个个人觉得挺好的函数符合w3c标准,作者把下载过程都放在这个函数的实现回调中:

UIImage *image = [UIImage sd_imageWithData:data]; image = [self scaledImageForKey:key image:image]; if (self.shouldDecompressImages) { image = [UIImage decodedImageWithImage:image]; } return image; 从磁盘找到图片后则将图片加入到内存缓存之中备用,符合w3c标准并通过block返回找到的Image.这里有个函数可以注意下:

void dispatch_barrier_async( dispatch_queue_t queue,在它之后加入队列的block,则等到这个block执行完毕后才开始执行. 而图片的下载根据头文件的定义有两种方式:

诶这个函数挺陌生的.我查了一下资料: category与associative作为objective-c的扩展机制的两个特性: category即类型,web前端制作可以通过它来扩展方法;associative,可以通过它来扩展属性. objc_getAssociatedObject、objc_setAssociatedObject、objc_removeAssociatedObjects都是Obj-c中的外联方法: object 参数作为待扩展的对象实例,承接网页制作key作为该对象实例的属性的键web切图报价,而value就是对象实例的属性的值,网站div+csspolicy作为关联的策略. plicy对应的枚举策略有: enum { OBJC_ASSOCIATION_ASSIGN = 0, OBJC_ASSOCIATION_COPY_NONATOMIC = 3, OBJC_ASSOCIATION_COPY = 01403 }; 看了有基础的也就应该大概懂这是什么意思了.这里就拓展下具体就不多说了. 其实这个用的也算是比较少的东西了.我觉得Category跟Protocol已经可以实现大部分的需求了. 不过这样看这个也好像挺有用处的.这里就当做顺便增加下知识储备了. 第三句:

// Cancel in progress downloader from queue NSMutableDictionary *operationDictionary = [self operationDictionary]; id operations = [operationDictionary objectForKey:key]; if (operations) { if ([operations isKindOfClass:[NSArray class]]) { for (id <SDWebImageOperation> operation in operations) { if (operation) { [operation cancel]; } } } else if ([operations conformsToProtocol:@protocol(SDWebImageOperation)]){ [(id<SDWebImageOperation>) operations cancel]; } [operationDictionary removeObjectForKey:key]; } 按照这个代码分析应该是在下载的时候取消当前所有的相同下载队列.但这里我有个问题:如果有某个图片下载还没完成又有同样的下载请求进来就会被取消web前端制作,这样循环的话这个图片不就没办法被下载.或许分析到最后我们能解决这个疑惑,div+css制作继续看接下来的代码. 第二行: objc_setAssociatedObject(self, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

二、委托到SDWebImageManager进行查找缓存下载图片: __block SDWebImageCombinedOperation *operation = [SDWebImageCombinedOperation new]; __weak SDWebImageCombinedOperation *weakOperation = operation; BOOL isFailedUrl = NO; @synchronized (self.failedURLs) { isFailedUrl = [self.failedURLs containsObject:url]; } 先检查下URL有没有在黑名单里面,web切图报价然后根据URL获得的一个Key去磁盘查找是否存在这个图片

typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) { //先进先出,html切图制作即队列模式(默认属性) SDWebImageDownloaderFIFOExecutionOrder, //先进后出,wap前端外包即栈模式 SDWebImageDownloaderLIFOExecutionOrder }; 下载部分则是使用NSURLConnetion来进行了.每一个图片的下载都是在一个独立队列中web前端制作,从而实现并发下载.这一部分就不细说了,web前端制作有兴趣的可以自己专研下源代码.在github上搜索SDWebImage即可找到原作者的源码.

点击次数:13010
作者:
web前端行业资讯
Web new NewsList
谷歌发布Tacotron2:能更简单地训练AI学习演讲 ,,2017年12月21日TensorFlow漏洞爆发背后:关于AI安全我们的傻与天真 ,,2017年12月21日Android端Edge浏览器新版发布:常规性能优化和BUG修复 ,,2017年12月21日三星开发出全球最小的DRAM芯片技术领先优势扩大 ,,2017年12月21日腾讯绝艺AI下一步将学习AlphaGozero自对弈训练 ,,2017年12月21日Facebook社交VR应用Spaces扩大覆盖面:入驻HTCVive ,,2017年12月21日设计图曝光:三星双屏折叠手机原来是这样的 ,,2017年12月21日微信支付和支付宝已成为世界移动支付的"老师" ,,2017年12月21日新专利表明FaceID未来有望装备在iPad、MacBook和iMac等设备 ,,2017年12月21日首批九个建议加入EE4J的项目 ,,2017年12月21日这就是SurfacePhone?微软可折叠手机概念图曝光 ,,2017年12月21日继“Angel”开源后,腾讯又开放TDinsight机器学习平台 ,,2017年12月21日谷歌母公司研发“闪光”网络技术无需铺设线缆 ,,2017年12月21日微软投资5千万美元利用人工智能对抗气候变化 ,,2017年12月21日谷歌中国2017:面向开发者的1年AI先行的1年 ,,2017年12月21日GreenKey加入Symphony软件基金会,将开源语音软件 ,,2017年12月21日腾讯发现者揭秘:怎么应对TensorFlow的安全风险,修复有多难 ,,2017年12月21日清华新成立两大交叉研究机构探索智能与未来 ,,2017年12月21日微软将AI融入生产力工具和搜索引擎与其它巨头竞争 ,,2017年12月21日Gfycat将利用机器学习技术创建高分辨率GIF动图 ,,2017年12月21日安全软件公司Avast开源化机器码反编译器RetDec ,,2017年12月21日谷歌开源TFGAN,让训练和评估GAN变得更加简单 ,,2017年12月21日社区对模块化不感兴趣时隔三周经典版FedoraServer27发布 ,,2017年12月21日Windows10加入OpenSSH客户端 ,,2017年12月21日FirefoxQuantum发布一个月安装量1.7亿 ,,2017年12月21日吴恩达宣布创业新项目已与富士康达成战略合作 ,,2017年12月21日Scala入门系列(十二):隐式转换2017年12月20日speedment入门教程2017年12月20日SLAM入门笔记(1):特征点的匹配2017年12月20日深入浅出了解frame和bounds2017年12月20日【leetcode】InsertInterval 【编程语言】2014年11月26日poj2778AC自动机与矩阵连乘【移动开发】2015年05月06日phoneGap打包 【移动开发】2015年09月10日学Photoshop必看高手的19句经典忠告2014年01月29日强大的复制工具Robocopy 【互联网】2015年01月13日【C语言探索之旅】第二部分第二课:进击的指针,C语言的王牌! 【综合】2015年03月03日如何抓取微信公共号的推送内容 【综合】2015年01月19日用Android得妹子 ,,2016年06月23日poj3280(CheapestPalindrome) 【数据库】2015年08月15日即时通讯服务器,ejabberd2.1.11发布 ,,2016年07月24日如何删除大量oracle中的小trace文件【移动开发】2014年12月12日信息在网络中的漫游(二) 【综合】2015年01月24日VB.Net视频总结【架构设计】2015年05月05日让百度三天就收录的诀窍2014年01月28日华为机试—去掉最大值、最小值后剩下的个数 【编程语言】2015年01月04日好玩的search加载css 【移动开发】2015年06月17日使用ajax技术无刷新动态调用股票信息2014年01月29日android中Toast显示时间自定义使用【编程语言】2015年08月07日javascriptiFrame研究2014年01月29日cookie和session的总结 【综合】2015年04月17日多图展示点击切换效果模拟的flash效果,点小图放大显示,再点恢复默认,2014年01月29日【POJ1700】CrossingRiver贪心,附贪心问题的一系列详细解析 【编程语言】2014年11月06日HBaseShell【编程语言】2015年09月20日git的概括,到现在为止,git的基本的操作我都讲完了 【数据库】2015年05月05日TED发布官方Android应用,超过1200多个演讲视频免费观看 ,,2016年07月24日Callable获取线程返回值 【编程语言】2015年06月17日CodeForces545B EquidistantString(模拟) 【编程语言】2015年09月17日重构wangEditor(web富文本编辑器),欢迎指正!【数据库】2014年12月23日关于类、私有属性与继承的理解2014年01月29日leetCode(26):UniqueBinarySearchTrees 【移动开发】2015年06月24日
我们保证
We guarantee
> psd效果文件手工切图,保证图片效果最好体积最小利于传输
> 100%手写的HTML(DIV+CSS)编码,绝对符合W3C标准
> 代码精简、css沉余量小、搜索引擎扫描迅速,网页打开快捷
> 应用Css Sprite能够减少HTTP请求数,提高网页性能
> 跨浏览器兼容(IE6、7、8、9,Firefox火狐,Chrome谷歌)