在了解AFN框架之前,先明白NSURLSession是什么
1. NSURLSession
NSURLSession是苹果官方提供的一套URL加载系统(URL Loading System),提供了通过URL获取资源的能力,通过标准https协议或其他自定协议。
该框架主要包含几个部分:
- URLSession:用来管理一组有关联性的网络传输任务
- URLSessionTask:一个网络传输任务,比如下载一个数据,需要通过URLSession执行
关联结构如下图所示:
NSURLSession的使用也相当简单
最简单的使用方法
- 通过
NSURLSession的shareInstance获取单例对象 - 创建一个
URLSessionDataTask对象,传入url - 调用
resume开始网络请请求
请求完成后会进行回调,有两种方式
- 在创建
URLSessionDataTask方法时传入的completeHandler进行回调 - 实现相关的delegate,通过delegate方法回调,参考下图
总体来说,NSURLSession的使用还是比较简单的,在功能简单时,直接使用没什么问题,但当业务复杂的时候,必然需要进行一些封装,AFNetworking的出现就提供了更丰富的接口设计和良好的扩展能力。
2. AFNetworking
2.1 有哪些特点?
AFNetworking框架非常强大,它基于NSURLSession框架封装,其特点如下:
- 系统接口封装:封装了与session、task创建、交互等细节
- 使用方便:使用者仅通过一次方法调用即可完成一次网络请求调用
- 可扩展性:可扩展的请求封装和回包封装
- 丰富的接口设计:
- 提供通知、block等多种形式的回调
- 对HTTP请求的封装
- 对UIKit进行扩展
2.2 整体架构设计
类图
AFNetworking的整体架构比较简单,最核心的类就是AFURLSessionManager,可以先看下整体类图:
关键类说明
- AFURLSessionManager
- 内部创建和管理NSURLSession对象,实现了NSURLSession的相关delegate回调,根据不同的task找到对应的delegate处理后续逻辑
- 对外暴露了创建dataTask的一系列接口,用于使用者进行网络请求,使用者主要关注NSURLRequest的创建和回调block的实现
- AFHTTPSessionManager
- AFURLSessionManager的子类,主要目的是方便构造HTTP请求,如GET、POST等,这个接口对于使用http协议访问的使用者会更方便一些
- AFURLSessionManagerTaskDelegate
- 在AFURLSessionManager内部实现,主要是用于与内部所创建的task绑定,记录请求过程中的进度、数据等,最后回调到使用者
- AFURLResponseSerialization
- 回包序列化协议,提供唯一接口responseObject,通过传入response、data、error对象,解析成对应的数据
- 实现类主要以数据维度区分,例如解析json数据、解析XML数据、解析图片数据
- AFURLRequestSerialization
- 请求序列化对象,提供唯一接口
requestBySerializingRequest:withParameters:error,用于创建一个请求包含了指定参数的request - 它的实现类AFHTTPRequestSerializer提供了HTTP请求头中常用的一些参数设置,例如是否允许蜂窝网络、缓存策略等,使用者可以通过参数快速修改http请求头中的数据,以及通过接口parameters提供自定义的参数
- sessionManager持有该对象,使用者可自行实现该接口从而实现不同的行为策略
- 请求序列化对象,提供唯一接口
时序图
请求创建的过程:
- 调用httpSessionManager的GET接口,开始触发协议请求
- httpSessionManager内部会通过requestSerializer创建一个request对,在调用基类的dataTask接口获取一个dataTask
- 基类urlSessionManager通过内部的session对象创建dataTask,同时会创建一个对应的taskDelegate,将task与taskDelegate绑定起来,返回dataTask
- 使用者调用resume开始请求流程
请求回包后流程:
- 请求回来后,首先由session对象通过delegate回调到urlSessionManager中
- urlSessionManager收到delegate后,会通过block回调到使用者,同时也会找到task对应的taskDelegate,处理相关逻辑,如更新进度、数据更新
- 当收到didComplete回调后,taskDelegate会通过responseSerializer处理回包数据,转换成对应的格式,最终通过最开始传进来的completeBlock回调到上层
小结
总体来说,AFN的代码结构设计不复杂,其中一些设计巧妙之处:
- 通过RequestSerialization和ResponseSerialization策略模式,可以让我们非常容易控制请求头的生成和回包的处理
- taskDelegate和task绑定的机制,将不同task的事件处理隔离开
同时,虽然整体结构很简单,但AFN作为一个广受好评的开源框架,其代码实现考虑的非常全面,从多线程的处理、接口设计、一些基本请求serializaer类诸如JSON、XML的实现、UIKIt的扩展等,基本覆盖了日常开发使用的方方面面,足以见得其用心之处。
在具体到比较复杂的业务场景的使用,可以进行一定程度的封装,比如继承AFHttpSessionManager,将请求头的默认参数如全局公用的UserAgent、通用域名等封装起来,以及一些基本的日志、上报等能力封装,能够让业务开发更方便简单。