美文网首页iOS开发
AFNetworking源码阅读

AFNetworking源码阅读

作者: 智小融 | 来源:发表于2018-03-26 11:26 被阅读19次

    AFNetworking是我们常用的网络库,我们有必要对其有必要的了解,以便进行二次封装和遇到问题时能及时的进行调试。而AF本身是对系统的NSURLSession进行的封装,所以想了解AF的整体架构,有必要先了解一下OC对于网络请求的基本姿势。

    一个简单的网络请求

        NSURL *url = [NSURL URLWithString:@"http://www.apple.com"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        NSURLSession *holdSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
        
        NSURLSessionDataTask * dataTask =  [holdSession dataTaskWithRequest:request completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error) {
            NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
            NSLog(@"******%@\n%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],res.allHeaderFields);
            if (error) {
                NSLog(@"******error:%@",[error localizedDescription]);
            }
        }];
        
        [dataTask resume];
    
    

    构建一个网络请求:

    第一步:先准备一个URL组建成NSRequest

    第二步:根据配置信息NSURLSessionConfiguration构建一个会话NSURLSession

    第三步:给NSURLSession分配一个数据请求的任务dataTaskWithRequest

    第四步:异步发送请求,处理回调的数据。

    看来我们用系统API发送一个网络请求还是很方便的啊!但是构建一个稳定高效的网络系统,我们还是有很多坑要填的,我们就来看下AFNetworking吧。

    AFNetworking的基本架构

    AFNetworking.png

    右侧为非核心模块:

    Security模块:为安全模块,处理https链接中的SSL相关配置。

    UIKit模块:为一些系统类的拓展和辅助功能,像图片的缓存,相关网络控件网络事件的监控。

    Reachability是AF自己封装的监测网络状态的模块。

    左侧为网络请相关核心模块

    AFHTTPRequestSerializer本事是一个协议,就一个方法。这个方法传入两个参数:NSURLRequest和URL参数字典,返回一个NSURLRequest。目的是实现对应前面栗子中NSURLRequest进行封装,主要是对于请求头和各种请求形态的编码预处理,达到http请求的要求。下面是对其包含的相关类进行一下说明。

    主要有三种请求格式:
    大部分的请求都是AFHTTPRequestSerializer这个来完成的也是默认的配置,另外还有AFJSONRequestSerializer和AFPropertyListRequestSerializer两种请求类型,这两者都是继承与AFHTTPRequestSerializer,主要在于前者用于特别的处理请求content-type是json文件的时候,后者用于特别的处理请求content-type是plist文件的时候。

    AFQueryStringPair实现对网络请求数据进行编码并组建成键值对用=连接,编码相关问题可以来这里看。主要是内联函数AFPercentEscapedStringFromString实现了相关设置。

    AFStreamingMultipartFormData主要用于文件上传时的一些设置。它其中有一个主要属性就是AFMultipartBodyStream,其继承于NSInputStream,是对读取上传资源文件流的一些设置。

    AFHTTPBodyPart主要是post或put请求中的请求体相关的设置

    AFURLResponseSerialization类本身也是一个协议,该方法传入一个response和一个data返回指定类型的对象。这个协议用于出来网络请求返回的数据response,对数据进行验证、解码,并根据MIME类型返回正确的数据。

    AFHTTPResponseSerializer下面其他几个类型的基类,用于验证返回的数据是否正确,确认解码方式,code码等。

    AFJSONResponseSerializer处理application/json、text/json、text/javascript数据,我们最常用的出具处理方式,返回序列化后的id对象。

    AFXMLParserResponseSerializer和AFXMLDocumentResponseSerializer处理application/xml、text/xml数据。前者生成NSXMLParser对象,后者生成NSXMLDocument对象。

    AFPropertyListResponseSerializer处理application/x-plist数据

    AFImageResponseSerializer处理image这个主类型下所有类型

    AFCompoundResponseSerializer应对多种处理类型,自行判断可以处理的类型。

    AFHTTPSessionManager继承与AFURLSessionManager,针对HTTP请求的各种请求类型进行了封装,主要目的是对外提供便于使用的接口,这里实现了栗子中,NSURLRequest的准备,拿到对应的task,并对task进行启动。

    AFURLSessionManager核心类,实现对task请求的hook,准备session,监控session的各种代理状态,监控task的各种代理状态,并利用AFURLResponseSerialization进行数据的解析与回调。

    NSURLSessionConfiguration是比较重要的配置信息类,三个初始化方法:

    • +defaultSessionConfiguration返回标准配置,共享NSHTTPCookieStorage,共享NSURLCache和共享NSURLCredentialStorage;
    • +ephemeralSessionConfiguration返回一个预设配置,没有持久性存储的缓存,Cookie或证书;+
    • +backgroundSessionConfiguration:它会创建一个后台session,它以在应用程序挂起,退出,甚至崩溃的情况下运行上传和下载任务。

    _AFURLSessionTaskSwizzling实现对resume、suspend的hook,并发送通知。

    AFURLSessionManagerTaskDelegate实现对task的上传、下载进度的回调,获取数据,获取到完整数据后进行回调。

    AFNetworking的线程相关问题

    网络的重点在于数据的高并发处理,所以有必要研究一下AF在线程方面所做的努力。

     self.operationQueue = [[NSOperationQueue alloc] init];
     self.operationQueue.maxConcurrentOperationCount = 1;
     self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
    

    AF创建session的时候会建一个队列传进去,这个队列默认设置最大并发数只有1,第一次这个session启动一个任务的时候启动一个线程来处理这个网络请求任务,以后这个会话下的任务默认都是在这个线程中顺序执行得。

    - (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
                forTask:(NSURLSessionTask *)task
    {
        NSParameterAssert(task);
        NSParameterAssert(delegate);
    
        [self.lock lock];
        self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
        [delegate setupProgressForTask:task];
        [self addNotificationObserverForTask:task];
        [self.lock unlock];
    }
    

    session每次启动一个任务,就会创建一个AFURLSessionManagerTaskDelegate的delegate对象,用于处理数据。AFHTTPSessionManager有一个字典属性mutableTaskDelegatesKeyedByTaskIdentifier用于存放以taskID为键,delegate对象为值得一组数据,这个delegate对象就是AFURLSessionManagerTaskDelegate生成的对象。此处为应对可能在不同的线程生成任务,添加了锁,防止线程竞争造成的数据异常。

     dispatch_async(url_session_manager_processing_queue(), ^{
                NSError *serializationError = nil;
                responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
    
                .......
                
                dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
                    if (self.completionHandler) {
                        self.completionHandler(task.response, responseObject, serializationError);
                    }
    
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
                    });
                });
            });
    

    此处代码是数据回来之后,对数据的处理。由于要处理的数据可能很大,所以首先开启一个异步并发队列url_session_manager_processing_queue,在子线程中处理数据,处理完成后再回调到应该去的线程。通过异步group,判断是否用户创建了group,如果没有就创建一个,同时判断用户是否创建了完成的队列completionQueue,如果没有就返回到主线程。理我可以监听自定义group,可以实现多个请求完毕后的统一处;通过设置自定义completionQueue,可以让我们的数据返回到自定义线程,一个场景就是返回的数据可能要进行大量的计算,这个时候我们没必要返回主线程,直接去自定义的子线程做这些复杂计算,待完成后再回到主线程去刷新UI。最后还有一个点就是为了保证通知在主线程,特地做了异步返回主线程去发通知。

    总结:

    AFNetworking面向接口编程,整体架构清爽,每个点拓展开来都有不少内容,值得我们学习,我只是对架构进行了整体的分析,希望对大家有所启发。闲来无事大家可以就感兴趣的一些模块仔细阅读,定会对整个网络请求以及线程的管理有更多的理解。

    相关文章

      网友评论

        本文标题:AFNetworking源码阅读

        本文链接:https://www.haomeiwen.com/subject/ufalcftx.html