源码分析
(test工程+源码注释工程)https://www.dropbox.com/sh/v7poaxekotxlaf1/AADQb7NbrrfHXJLrBt1Q51vVa?dl=0
整体的流程图
创建Session用来发送请求,可以自定义创建,也可以直接使用AF单例,默认的Session来发送请求
外部调用request()方法,传入URLConvertible,创建Request对象
- 内部开始先用URLConvertible来创建URLRequestConvertible对象
- 用URLRequestConvertible创建Request(这个Request就是返回给外部的对象),保存到Session中,然后开始对Request进行预处理
- 先创建初始URLRequest,用预处理器对其进行预处理,在预处理前后都有使用方法来告知Request,流程变更,用来通知事件监听器,所以看EventMonitor协议中,有一大堆生命周期的回调事件。
- 预处理完成,返回Request对象
外部调用response系列方法,在这些方法中实现对响应的处理
- 内部会先创建对原始响应数据的处理闭包
- 先解析响应(还记录了解析所花的时间)
- 解析失败的重试
- 解析成功执行外部传入的完成回调
- 把这个闭包追加保存到Request的responseSerializers数组中
- 检测下当前Request是不是已经完成了,完成的话重新标记成执行中
- 检测下当前Request是否已经完成了全部响应的解析,如果是的话,就手动执行processNextResponseSerializer()方法开始继续执行responseSerializers数组中的解析闭包
- 检测下当前Request是否需要发送请求,需要的话,就调用resume()方法发送请求
AF.request为例,调用情况
简单的request请求,并对request后的AFDataResponse<String>
不做处理
func requestAction() {
/// 打印百度的htmlString
/// 网址string是作为URLConvertible协议类型传入,实现一个asURL的方法转换为URL
AF.request("https://www.baidu.com").responseString {
resp in
switch resp.result {
case let .success(str):
debugPrint("request success:\(str)")
case let .failure(err):
debugPrint("request fail:\(err)")
}
}
}
输入的是String
类型的"https://www.baidu.com"
,输入的网址string是作为URLConvertible协议类型传入的,该协议可以看作是URL类型的协议抽象,需要实现一个asURL
的方法,用来生成请求用的URL。
跳到第一个方法
使用传入的参数调用RequestEncodableConvertible()方法创建了一个convertible局部变量,类型只是个简单的结构体,实现了URLRequestConvertible协议类型
/// request 默认是get请求
open func request(_ convertible: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil,
interceptor: RequestInterceptor? = nil,
requestModifier: RequestModifier? = nil) -> DataRequest {
let convertible = RequestConvertible(url: convertible,
method: method,
parameters: parameters,
encoding: encoding,
headers: headers,
requestModifier: requestModifier)
return request(convertible, interceptor: interceptor)
}
第二个方法
使用入参的convertible + 拦截器对象
Session所持有的rootQueue(回调执行队列),serializationQueue(响应解析队列),eventMonitor(事件监听器对象),以及把自己作为RequestDelegate对象,构建出了DataRequest对象
open func request(_ convertible: URLRequestConvertible, interceptor: RequestInterceptor? = nil) -> DataRequest {
let request = DataRequest(convertible: convertible,
underlyingQueue: rootQueue,
serializationQueue: serializationQueue,
eventMonitor: eventMonitor,
interceptor: interceptor,
delegate: self)
perform(request)
return request
}
第三个方法
使用了rootQueue队列执行,先判断request要是取消了的话,直接return
/// 准备发送请求 主入口
func perform(_ request: Request) {
rootQueue.async {
//现在rootQueue中判断是否请求被取消
guard !request.isCancelled else {
return }
//塞入到正在请求的Request集合中
self.activeRequests.insert(request)
//在requestQueue队列发送请求
self.requestQueue.async {
// Leaf types must come first, otherwise they will cast as their superclass.
switch request {
//Request为uploadRequest
//然后在rootQueue告知事件监听器didCreateUploadable, 然后调用performSetupOperations方法
//创建失败的话先在rootQueue告知监视器didFailToCreateUploadable, 错误消息为createUploadableFailed
//然后在request中决定是否重试
case let r as UploadRequest: self.performUploadRequest(r) // UploadRequest must come before DataRequest due to subtype relationship.
//直接调用performSetupOperations
case let r as DataRequest: self.performDataRequest(r)
//如果是新建下载, 直接调用performSetupOperations方法
//如果是断点续传, 在rootQueue调用didReceiveResumeData方法, 详见下方断点续传部分
case let r as DownloadRequest: self.performDownloadRequest(r)
///直接调用performSetupOperations
case let r as DataStreamRequest: self.performDataStreamRequest(r)
default: fatalError("Attempted to perform unsupported Request subclass: \(type(of: request))")
}
}
}
}
调用了performDataRequest
//直接调用performSetupOperations
case let r as DataRequest: self.performDataRequest(r)
第四个方法
检测是否在RequestQueue
执行,然后继续调用performSetupOperations()
方法继续处理
/// 处理成功后, 会调用didCreateURLRequest方法来更新状态
func performDataRequest(_ request: DataRequest) {
//当前在requestQueue
dispatchPrecondition(condition: .onQueue(requestQueue))
performSetupOperations(for: request, convertible: request.convertible)
}
第五个方法
- 构建原始URLRequest对象T
- 对T进行有效行校验
- 告知Request,T已经初始化完成,把T传给Request进行内部处理
- 如果Request中有请求适配器,逐一调用适配器对T进行处理
- 处理完成之后,告知Request已经适配完成
- 最终调用didCreateURLRequest()方法完成
func performSetupOperations(for request: Request,
convertible: URLRequestConvertible,
shouldCreateTask: @escaping () -> Bool = {
true })
{
//当前在RequestQueue
dispatchPrecondition(condition: .onQueue(requestQueue))
//URLRequestConvertible生成的URLRequest
let initialRequest: URLRequest
do {
initialRequest = try convertible.asURLRequest()
//检测请求是否有效(get请求不能带body参数)
try initialRequest.validate()
} catch {
//在rootQueue队列上报错误
rootQueue.async {
request.didFailToCreateURLRequest(with: error.asAFError(or: .createURLRequestFailed(error: error))) }
return
}
//在rootQueue通知request,初始化URLRequest成功
rootQueue.async {
request.didCreateInitialURLRequest(initialRequest) }
//检查是否有请求适配器
guard !request.isCancelled else {
return }
guard let adapter = adapter(for: request) else {
guard shouldCreateTask() else {
return }
//没有拦截器的话直接通知
rootQueue.async {
self.didCreateURLRequest(initialRequest, for: request) }
return
}
//使用拦截器中的适配器来预处理请求
adapter.adapt(initialRequest, for: self) {
result in
do {
let adaptedRequest = try result.get()
try adaptedRequest.validate()
//通知处理完成
self.rootQueue.async {
request.didAdaptInitialRequest(initialRequest, to: adaptedRequest) }
guard shouldCreateTask() else {
return }
self.rootQueue.async {
self.didCreateURLRequest(adaptedRequest, for: request) }
} catch {
//任何错误都抛出requestAdaptationFailed错误
self.rootQueue.async {
request.didFailToAdaptURLRequest(initialRequest, withError: .requestAdaptationFailed(error: error)) }
}
}
}
因为没有拦截器所以调用了didCreateURLRequest(initialRequest, for: request)
第六个方法
/// 当创建请求完成, 拦截适配器处理完成之后, 就会来到这里的逻辑
func didCreateURLRequest(_ urlRequest: URLRequest, for request: Request) {
dispatchPrecondition(condition: .onQueue(rootQueue))
///通知创建request成功
request.didCreateURLRequest(urlRequest)
guard !request.isCancelled else {
return }
// 创建URLSessionTask,基类Request为实现该方法,几个子类各自实现 ```
let task = request.task(for: urlRequest, using: session)
// 写入session的request—Task数据队列保存
requestTaskMap[request] = task
// 线程安全保存task
request.didCreateTask(task)
updateStatesForTask(task, request: request)
}
request.task(for: urlRequest, using: session)
创建了URLSessionTask
,这就是真正用来发送请求的task,然后把这个task存在了Session的requestTaskMap字典中,key是request,这样可以在任意时候根据request找到它所对应的task。开始发送请求。
AF对请求的处理完成
Response (接受响应)处理
Request() -> response()
因为写的是responseString
第一步
唯一需要必须传入的参数就是完成的回调闭包
completionHandler: @escaping (AFDataResponse<String>) -> Void) -> Self
/// Adds a handler using a `StringResponseSerializer` to be called once the request has finished.
/// 添加解析方法
/// - Parameters:
/// - queue: The queue on which the completion handler is dispatched. `.main` by default.
/// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
/// `completionHandler`. `PassthroughPreprocessor()` by default.
/// - encoding: The string encoding. Defaults to `nil`, in which case the encoding will be determined
/// from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
/// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
/// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
/// - completionHandler: A closure to be executed once the request has finished.
///
/// - Returns: The request.
@discardableResult
public func responseString(queue: DispatchQueue = .main,
dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
encoding: String.Encoding? = nil,
emptyResponseCodes: Set<Int> = StringResponseSerializer.defaultEmptyResponseCodes,
emptyRequestMethods: Set<HTTPMethod> = StringResponseSerializer.defaultEmptyRequestMethods,
completionHandler: @escaping (AFDataResponse<String>) -> Void) -> Self {
response(queue: queue,
responseSerializer: StringResponseSerializer(dataPreprocessor: dataPreprocessor,
encoding: encoding,
emptyResponseCodes: emptyResponseCodes,
emptyRequestMethods: emptyRequestMethods),
completionHandler: completionHandler)
}
执行的是response(
第二步
对数据进行一大堆的逻辑、解析处理
/// Adds a handler to be called once the request has finished.
/// 使用自定义解析器解析
/// - Parameters:
/// - queue: The queue on which the completion handler is dispatched. `.main` by default
/// - responseSerializer: The response serializer responsible for serializing the request, response, and data.
/// - completionHandler: The code to be executed once the request has finished.
///
/// - Returns: The request.
@discardableResult
public func response<Serializer: DataResponseSerializerProtocol>(queue: DispatchQueue = .main,
responseSerializer: Serializer,
completionHandler: @escaping (AFDataResponse<Serializer.SerializedObject>) -> Void)
-> Self {
appendResponseSerializer {
// Start work that should be on the serialization queue.
// 开始解析响应, 必须在响应解析队列完成, 因为有解析操作, 所以开始计时
let start = ProcessInfo.processInfo.systemUptime
// 用入参解析器解析数据,catch错误并转换成AFError
let result: AFResult<Serializer.SerializedObject> = Result {
try responseSerializer.serialize(request: self.request,
response: self.response,
data: self.data,
error: self.error)
}.mapError {
error in
error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
}
// 用app启动的时间差值来计算出解析所花的时间
let end = ProcessInfo.processInfo.systemUptime
// End work that should be on the serialization queue.
// 用request内部队列来继续处理