美文网首页
Alamifire的Response解析

Alamifire的Response解析

作者: Lucas汪星人 | 来源:发表于2018-08-30 17:32 被阅读41次
    image

    女儿惹她妈妈生气了,我让她去道歉。
    “知错就改,快去找你妈,认错。”我催促她。
    小家伙犹豫了半天,终于走进了厨房,对她妈说道:
    “妈妈,请问你是周二珂吗?”
    妻子很疑惑:“不是啊。”
    “哦,对不起,我认错了。”

    哈哈哈,意淫下。


    最近看Alamifire的源码,不得不说,好的源码的确让人获益良多。

    但是看之前会很懵,如果不熟悉请求流程的话,很有可能坚持不下去,所以我这里简要的把他的一个请求流程简单分析一下,希望能够帮助到你。

    Alamofire.request(posturl, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headerFile).responseJSON { (response) in
            switch response.result{
            case .success(_):
                    ///成功
                if let value = response.result.value {
                    
                }
            case .failure(_):
                    ///失败
                print(response.result.error)
              }
        }
    

    上面是一个请求json数据的一个标准用法,看源码可以发现Alamofire提供了多个静态的请求方法,而这些请求方法全部是通过SessionManager管理的。

    网图,侵删

    由于Alamofire本质上是对URLSession的的一个封装,所以我们需要了解下URLSession的结构,如上图一个session管理者多个请求的task和回调的delegate。所以在SessionManager中我们可以看到一个静态的default常量,以及类型为SessionDelegate的一个delegate变量。


    接下来我们分析上面的请求过程

    首先Alamofire将请求分成了几个大类

    image

    这里我就不一个个分析了,今天主要分析请求的流程。后面我会针对Alamofire中几个比较怪的写法,我们不经常用的写法分析一下。

    Alamofire.request这个方法调用的是SessionManager中的DataRequest的方法

    open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
        var originalRequest: URLRequest?
    
        do {
            originalRequest = try urlRequest.asURLRequest()
            let originalTask = DataRequest.Requestable(urlRequest: originalRequest!)
    
            let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
            let request = DataRequest(session: session, requestTask: .data(originalTask, task))
    
            delegate[task] = request
    
            if startRequestsImmediately { request.resume() }
    
            return request
        } catch {
            return request(originalRequest, failedWith: error)
        }
    }
    

    返回值还是DataRequest,这是为了后面可以链式调用.responseJSON


    这里的请求步骤简单来说是(这里还需要再研究下,回头会专门写个文章仔细分析下)

    • 获取urlRequest

    • 获取URLSessionTask

    • sessionURLSessionTask封装至Request相应的子类对象

    这句delegate[task] = request可能一开始看很难看懂,但其实这是给SessionDelegate定义了下标方法,其实是通过SessionDelegaterequests属性来存储task对应的request

    ///通过自身的requests属性来存储[task: request],用lock来确保线程安全。
    /// Access the task delegate for the specified task in a thread-safe manner.
    open subscript(task: URLSessionTask) -> Request? {
        get {
            lock.lock() ; defer { lock.unlock() }
            return requests[task.taskIdentifier]
        }
        set {
            lock.lock() ; defer { lock.unlock() }
            requests[task.taskIdentifier] = newValue
        }
    }
    

    后面的.responseJSON这里是指定对返回的数据进行json解析

    public func responseJSON(
        queue: DispatchQueue? = nil,
        options: JSONSerialization.ReadingOptions = .allowFragments,
        completionHandler: @escaping (DataResponse<Any>) -> Void)
        -> Self
    {
        return response(
            queue: queue,
            responseSerializer: DataRequest.jsonResponseSerializer(options: options),
            completionHandler: completionHandler
        )
    }
    

    相信大家看到这里头肯定大了一圈,讲真的,我看到这里头大的一度想放弃。

    [图片上传失败...(image-5840f4-1535621411864)]

    但是头大了之后发现能思考更多东西了,这里我来一个一个分解开来

    public func response<T: DataResponseSerializerProtocol>(
        queue: DispatchQueue? = nil,
        responseSerializer: T,
        completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
        -> Self
    {
        delegate.queue.addOperation {
            let result = responseSerializer.serializeResponse(
                self.request,
                self.response,
                self.delegate.data,
                self.delegate.error
            )
    
            var dataResponse = DataResponse<T.SerializedObject>(
                request: self.request,
                response: self.response,
                data: self.delegate.data,
                result: result,
                timeline: self.timeline
            )
    
            dataResponse.add(self.delegate.metrics)
    
            (queue ?? DispatchQueue.main).async { completionHandler(dataResponse) }
        }
    
        return self
    }
    

    首先return调用了DataRequest的一个序列化结果的一个根方法,为什么说根方法呢,大家可以看下responseString这个方法中也是return这个方法,通过<T: DataResponseSerializerProtocol>这个泛型参数就可以实现请求结果序列化成任意类型,只要遵守了DataResponseSerializerProtocol这个协议,并实现即可。

    而这个协议中的serializeResponse这个闭包则是起到传输数据然后返回序列化的结果的一个作用。


    下面我阐述下代码调用的顺序。

    1. 调用.responseJSON ————> 传入responseSerializer这个参数(系列化的过程)来调用DataRequest的序列化根方法

    2. DataRequest.jsonResponseSerializer(options: options)这里就是序列化的方法,我尽量在注释中描述清楚

       public static func jsonResponseSerializer(
           options: JSONSerialization.ReadingOptions = .allowFragments)
           -> DataResponseSerializer<Any>
       {
            ///返回的是遵守DataResponseSerializerProtocol协议的一个结构体对象
            ///这是一个初始化方法,初始化的对象存储了一个闭包。
           return DataResponseSerializer { _, response, data, error in
               return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
           }
           
           ///所以上面可以等价为
           let jsonResponseSerializer = DataResponseSerializer.init { (request, response, data, error) -> Result<Any> in
           
                       ///这里就是根据闭包传过来的response, data, error来对结果进行序列化。
           return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
               
           }
           return jsonResponseSerializer
           
       }
      
    3. 接下来看DataRequest的序列化根方法的实现,我们可以看到

       let result = responseSerializer.serializeResponse(
               self.request,
               self.response,
               self.delegate.data,
               self.delegate.error
           )
      

    这里的responseSerializer.serializeResponse传递参数然后调用第二步中序列化操作,最后得到return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)返回值

    1. 最后将得到的序列化结果result以及其他数据封装在dataResponse中通过completionHandler在指定线程中回调。

       var dataResponse = DataResponse<T.SerializedObject>(
               request: self.request,
               response: self.response,
               data: self.delegate.data,
               result: result,
               timeline: self.timeline
           )
      

    这里对协议的关联类型以及属性的应用值得我们认真拜读一下

    最终

    最近很迷茫,来个人私信我陪我聊聊骚啊。

    联系方式

    相关文章

      网友评论

          本文标题:Alamifire的Response解析

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