SDWebImage 源码解读之网络请求层SDWebImageDownloader

本章开始将介绍SDWebImage库中的核心类SDWebImageDownloader,该类是SDWebImage库进行网络加载的底层操作核心所在,理解了该类的实现思想,就能知道SDWebImage库的网络加载策略是如何的。首先解释一下涉及到的一些基本概念和方法:

•OC中的反射机制

反射是计算机程序在运行时检查、内省、修改自身结构和行为的一种能力。这样的能力可以让一个给定的程序动态地适应不同的情况。OC语言中的OC对象,都继承自NSObject类。这个类为我们提供了一些基础的方法和协议,我们可以直接调用从这个类继承过来的方法。本篇文章中讲到的反射方法,就在NSObject和Foundation框架中。Foundation框架为我们提供了一些反射的API方法,我们可以通过这些API执行将字符串转为SEL等操作。由于OC语言的动态性,这些操作都是发生在运行时的。

// SEL和字符串转换

FOUNDATION_EXPORT    NSString *NSStringFromSelector(SEL aSelector);

FOUNDATION_EXPORT    SEL NSSelectorFromString(NSString *aSelectorName);

// Class和字符串转换

FOUNDATION_EXPORT    NSString *NSStringFromClass(Class aClass);

FOUNDATION_EXPORT    Class __nullable NSClassFromString(NSString *aClassName);

// Protocol和字符串转换

FOUNDATION_EXPORT    NSString *NSStringFromProtocol(Protocol *proto) NS_AVAILABLE(10_5, 2_0);

FOUNDATION_EXPORT    Protocol * __nullable NSProtocolFromString(NSString *namestr) NS_AVAILABLE(10_5, 2_0);

// 假设从服务器获取JSON串,通过这个JSON串获取需要创建的类为ViewController,并且调用这个类的getDataList方法。

Class class = NSClassFromString(@"ViewController");

ViewController *vc = [[class alloc] init];

SEL selector = NSSelectorFromString(@"getDataList");

[vc performSelector:selector];

通过这些方法,我们可以在运行时选择创建实例,并动态选择调用哪个方法。这些操作甚至可以由服务器传回来的参数来控制,我们可以将服务器传回来的类名和方法名,实例为我们的对象。

使用反射机制的优点:

1.可以弱化连接,他并不会把没有的Framework也link到程序中

2.不需要使用import,因为类是动态加载的,只要存在就可以加载

使用反射机制的缺点:

1.不利于维护。使用反射模糊了程序内部实际发生的事情,隐藏了程序的逻辑。这种绕过源码的方式比直接代码更为复杂,增加了维护成本。

2.性能较差。使用反射匹配字符串间接命中内存比直接命中内存的方式要慢。当然,这个程度取决于使用场景,如果只是作为程序中很少涉及的部分,这个性能上的影响可以忽略不计。但是,如果在性能很关键的应用核心逻辑中使用反射,性能问题就尤其重要了。

•dispatch_barrier_async 和dispatch_barrier_sync

dispatch_barrier_(a)sync,可以翻译成栅栏(barrier),它可以往队列里面发送任务(块,也就是block),这个任务有栅栏(barrier)的作用。在队列中,barrier块必须单独执行,不能与其他block并行。这只对并发队列有意义,并发队列如果发现接下来要执行的block是个barrier block,那么就一直要等到当前所有并发的block都执行完毕,才会单独执行这个barrier block代码块,等到这个barrier block执行完毕,再继续正常处理其他并发block。

假设我们原先有6个任务要执行,我们现在要插入一个任务0,这个任务0要在1、2、3都并发执行完了之后才能执行,而4、5、6号任务要在这个任务0结束后才允许并发。dispatch_barrier_sync和dispatch_barrier_async的共同点:

1、都会等待在它前面插入队列的任务(1、2、3)先执行完

2、都会等待他们自己的任务(0)执行完再执行后面的任务(4、5、6)

dispatch_barrier_sync和dispatch_barrier_async的不共同点:

在将任务插入到queue的时候,dispatch_barrier_sync需要等待自己的任务(0)结束之后才会继续程序,然后插入被写在它后面的任务(4、5、6),然后执行后面的任务,而dispatch_barrier_async将自己的任务(0)插入到queue之后,不会等待自己的任务结束,它会继续把后面的任务(4、5、6)插入到queue,所以,dispatch_barrier_async的不等待(异步)特性体现在将任务插入队列的过程,它的等待特性体现在任务真正执行的过程。

使用dispatch_barrier_sync结果如下:

使用dispatch_barrier_async结果如下:

下面开始对SDWebImageDownloader类的实现思路进行解读,先看看下面使用了反射机制的代码段:

该方法使用反射机制在程序运行期间去判断工程当中是否有引入了另一个第三方库SDNetworkActivityIndicator.h,而不是一开始就将该库引进工程中,使用#import "SDNetworkActivityIndicator.h"的方式进行引用,弱化了对一些其他库的依赖关系。在该类中添加了两个观察者通知,通过loading加载视图的出现与消失来表示SDWebImageDownloaderOperation网络请求的状态。下面开始主要讲解SDWebImageDownloader类中关键的几个方法:

该方法判断当前请求操作的合法性,若要进行网络加载,则必须保证progressBlock,completedBlock有存在对应的初始化操作,同时请求的URL并没有缓存在self.URLCallbacks数组中,这样请求操作createCallback()才会执行,同时网络请求会在所有的并发请求都执行完之后,才会执行dispatch_barrier_sync(self.barrierQueue, ^{});代码块中的内容,以保证网络请求操作是有序执行,而不是无序的并发执行。

该方法是SDWebImageDownloader类的关键方法,在经过网络请求合法性性的判断之后,便开始创建网络请求对象NSMutableURLRequest *request,调用SDWebImageDownloaderOperation已经封装好的网络请求任务执行图片的数据获取跟下载操作,在图片数据下载过程中,progress(),都会被持续执行去刷新当前的图片数据大小,知道图片完全被下载完成。而在图片下载操作完成或者取消操作下都需要对当前请求的图片URL进行移除,不进行移除的情况下,在下次调用- (void)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL *)url createCallback:(SDWebImageNoParamsBlock)createCallback方法进行合法性校验是就会存在旧值,导致网络请求无法实时的进行下载更新。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容