AFNetworking源码——多线程(2.0 & 3.
2017-07-29 本文已影响524人
郑明明
由于AFNetworking本质上是对NSURLConnection和NSURLSession进行了封装设计,作为一个优秀网络请求框架,必然对多线程这一块的处理有自己的良好设计,本文分别探究2.0和3.0时代对于多线程的设计方案
AFNetworking 2.0
对于2.0时代,框架采用了NSURLConnection+NSOperation的模型,那么来分析一下AF是如何进行请求的管理,以及回调的处理的,我们尝试列出几种方案:
-
所有请求都在主线程中发送,并且回调处理也有主线程来完成
这应该是最直接的方式,那我们来看下这个方式有什么不好的地方- 如果请求数量很多,那么主线程会消耗大量的CPU资源来做请求的发送和回调的处理,对于这么注重流畅度的iOS,该方法直接被淘汰了
-
开启一条子线程,在子线程中进行请求的同步发送,并且等待回调
利用子线程做处理,就不会有上述问题,但是仍然存在一些不好的地方- 子线程由于需要接受回调,所以需要使用runLoop进行线程保活,这样即使回调完成,线程资源仍然得不到释放,如果请求数量很多,就意味着开辟很多条子线程,造成大量的资源浪费
-
AF的方案:启用一个子线程,异步发送请求,处理回调事件
通俗来说,就是开辟一条专门用于请求管理的线程,下面为2.0中的源码
[self performSelector:@selector(operationDidStart)
onThread:[[self class] networkRequestThread] withObject:nil
waitUntilDone:NO
modes:[self.runLoopModes allObjects]]
AFNetworking 3.0
AF的3.0时代进行了大改动,其内部实现从基于NSURLConnection变成了NSURLSession,在3.0的设计思路这这篇文章中解析了3.0是如何对NSURLSession进行封装的,这里我们直接看一下对应的源码:
self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = 1;
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
- 3.0以AFURLSessionManager为核心类,每个对象都拥有一个NSOperationQueue用于请求发送和回调管理(可以发现是一个串行队列)
- 如果要转化为NSURLSession,那么就相当于每个session拥有一个NSOperationQueue,然后一个session可以创建多个任务,这些任务是在串行队列中执行
总结
之所以设计方式不同了,有原因来自:2.0时代的NSURLConnection是一个全局的设计,从调用方式也能发现:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"www.nineteen.me"]];
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * __nullable response, NSData * __nullable data, NSError * __nullable connectionError) {
// ...
}];
而NSURLSession是将Session和task进行了分离,可以从使用看出:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [session dataTaskWithURL:[[NSURL alloc]initWithString:@""]];
[task resume];
这样的设计就能够为每个session对象(AFURLSessionManager对象)添加独自的操作队列NSOperationQueue,分别进行各自的请求发送和回调管理。而2.0中使用全局设计,因此AF维护一条子线程专门用于管理所有的请求发送和回调处理。