Alamofire源码分析

本文详细介绍了Alamofire的请求流程,包括创建Session、构建Request、发送请求、响应处理等步骤。重点讲解了Request的创建、数据解析、自定义响应序列化、错误处理和重试机制。此外,还展示了如何使用AlamofireManager进行网络请求,以及如何自定义请求拦截器、事件监听器和缓存策略。最后,讨论了HTTPS的安全验证和证书管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

源码分析

(test工程+源码注释工程)https://www.dropbox.com/sh/v7poaxekotxlaf1/AADQb7NbrrfHXJLrBt1Q51vVa?dl=0

请添加图片描述

整体的流程图

请添加图片描述

创建Session用来发送请求,可以自定义创建,也可以直接使用AF单例,默认的Session来发送请求

外部调用request()方法,传入URLConvertible,创建Request对象

  1. 内部开始先用URLConvertible来创建URLRequestConvertible对象
  2. 用URLRequestConvertible创建Request(这个Request就是返回给外部的对象),保存到Session中,然后开始对Request进行预处理
  3. 先创建初始URLRequest,用预处理器对其进行预处理,在预处理前后都有使用方法来告知Request,流程变更,用来通知事件监听器,所以看EventMonitor协议中,有一大堆生命周期的回调事件。
  4. 预处理完成,返回Request对象

外部调用response系列方法,在这些方法中实现对响应的处理

  1. 内部会先创建对原始响应数据的处理闭包
    1. 先解析响应(还记录了解析所花的时间)
    2. 解析失败的重试
    3. 解析成功执行外部传入的完成回调
  2. 把这个闭包追加保存到Request的responseSerializers数组中
  3. 检测下当前Request是不是已经完成了,完成的话重新标记成执行中
  4. 检测下当前Request是否已经完成了全部响应的解析,如果是的话,就手动执行processNextResponseSerializer()方法开始继续执行responseSerializers数组中的解析闭包
  5. 检测下当前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内部队列来继续处理
            
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值