Alamofire學習 -- Request

前言

經過上一篇URlSession後臺下載,咱們已經知道了SessionManager的做爲整個Alamofire框架的核心樞紐的重要性🔐,還有一個比較重要的是SessionManager的代理SessionDelegate,封裝了URLSessionDelegate。負責對Task的回調事件提供默認實現(轉發給TaskDelegate進行實際處理),而且以閉包的方式暴露給外部,讓外部能夠自定義實現。TaskDelegateURLSessionTask的回調進行實際的處理,而且執行task的完成回調用。Request就 是對URLSessionTask的封裝,是暴露給上層的請求任務。json

Alamofire Request

廢話很少說直接來用URLSession建立一個request和利用Alamofire建立一個request的例子🌰看看:swift

首先來看一個URLSessionrequest的用法:數組

guard let url = URL(string: "https://www.douban.com/j/app/radio/channels") else {  
    return;  
}  
let dataTask = URLSession.shared.dataTask(with: url) { (data, response, error) in  
    guard let data = data else{  
        return;  
    }  
    do{  
        let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)  
        print(json)  
    }catch let error{  
        print(error)  
    }  
};  
dataTask.resume()  
複製代碼

再來看一個基礎的Alamofire.request用法:bash

Alamofire.request("https://www.douban.com/j/app/radio/channels").responseJSON { (response) in  
    if let JSONString = response.result.value {  
        print("JSONString: \(JSONString)")  
    }  
}  
複製代碼

有沒有以爲,若是使用系統的API,咱們不得不先建立URL,而後創建dataTask,而且resume,接着在callback裏去解析JSON。因爲Swift是一種強類型的語言,咱們不得不進行大量的邏輯判斷和try-catch🤦‍♂️。而Alamofire把這些步驟簡化成了一個靜態的方法調用,而且用鏈式的方式來處理異步的Response解析。因爲是鏈式的,咱們也能夠用鏈式的方式實現更多的邏輯。session

那麼在Alamofire.request的內部具體作了什麼「騷」操做呢🤔?沒辦法🤷‍♀️️,想要看到內部實現,就要看到這裏的源碼,那麼就來吧...閉包

根據Alamofire.request的這個方法,咱們來到Alamofire.swift看到這個request方法: app

能夠看到這個方法裏的幾個參數都有默認值,全部咱們能夠直接傳入一個 Url參數,這個方法返回一個 DataRequest對象,是利用 SessionManagerrequest方法,這說明了真正的 request應該是由 SessionManager發起的,下面再來看一下 SessionManager.default.request方法內部實現了什麼❓

在這個方法中建立了一個 URLRequest對象,並把傳入的參數傳入到這個 URLRequest對象中,並調用了 request方法,而且把上面建立的 URLRequest對象進行編碼以後做爲參數傳入到這個 request方法,

這裏是插入一個小插曲,這個參數編碼究竟是如何操做的,也就是這個encoding.encode()方法具體實現了什麼?框架

這裏先取出請求方法的類型,而後根據不一樣的類型對參數進行不一樣的編碼,由前面的代碼咱們知道在 encode()這個方法傳入了參數 parameters,而在這裏處理這個 parameters的是 query(parameters),那麼接着來看這個 query方法的具體實現:

來到這裏把傳入的參數根據key進行排序,而後遍歷排序的結果,而後利用queryComponents方法將全部的參數(key,value)不斷的遞歸, 返回一個元素爲元組的數組,而後將這個數組進行map映射,將key=value而且拼接&符號,至此就完成了參數的拼接,異步

📣而後咱們在回到encode方法中,根據請求方法的不一樣,post

  • 若是請求方法是.get, .head, .delete類型,須要urlComponents.percentEncodedQuery進行百分號編碼,而且利用query(parameters)把參數直接拼接到URL後面。
  • 若是是其餘類型的請求方法,例如.post,須要設置請求頭application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type,而後利用query(parameters)拼接參數,將參數轉換爲二進制並賦值到urlRequest.httpBody請求體中。

那麼接下來回到request的流程再來看看這個request(encodedURLRequest)方法內部實現了什麼❓

在這裏先拿到傳入的已經編碼事後的URLRequest,這裏的DataRequest是繼承於Request的一個子類,用來管理URLSessionDataTask,而這裏DataRequest.Requestable,難道是調用了一個Requestable方法?咱們跟進去這個Requestable看一下:

能夠看到這個Requestable是一個結構體,也就是說在當前這個DataRequest類裏面嵌套了一個結構體,可是能夠看到這個結構體內部並無urlRequest這個方法,那它怎麼會調用urlRequest方法呢?

咱們來看這句代碼let urlRequest: URLRequest,能夠看到在這個結構體的內部有個urlRequest屬性,並且默認初始化。✍️那麼這句DataRequest.Requestable(urlRequest: )實際上就是建立了一個類型爲Requestable的並且包含建立task方法的結構體對象,在這個task方法的內部返回的是同步建立的sessionreturn queue.sync { session.dataTask(with: urlRequest) }.

🗣🗣🗣那麼這裏爲何不使用DataRequest直接建立一個task,而非要taskRequestable這個結構體來建立,實際上是Requestable結構體就至關因而DataRequest的祕書,其實這裏DataRequesttask任務應該是一一對應的,平級關係,若是DataRequest直接建立task,更像是歸屬關係,而由Requestable來建立task也就是下降了DataRequesttask的耦合性,使DataRequesttask保持平級關係。

繼續回到源代碼,能夠看到在 Requestable建立完 task以後,緊接着 DataRequest就建立了一個 request,那麼接下來來到 DataRequestinit方法,然而 DataRequest並無 init方法,那麼就看其父類 Requestinit方法:

能夠看到這裏 requestTask很明顯是個枚舉類型,

而這個 requestTask調用了一個關聯方法 .data(let originalTask, let task),而這個 .data 便是 DataRequest初始化方法中傳入的 .data(originalTask, task),這裏會根據傳入的方法的不一樣的類型來把 task交給不一樣的 TaskDelegate.

再一次回到request流程的源碼🤷‍♂️🤷‍♂️🤷‍♂️ ,這裏一句很重要的代碼 delegate[task] = request,這裏是作了一個綁定操做,(有點相似於字典和數組),當前這個delegate由源碼可知public let delegate: SessionDelegate是一個SessionDelegate就是SessionDelegate經過task能夠讀取到request。方便在 SessionDelegate 下發任務的時候,經過task直接檢索,方便直接獲取到request ,而後調用request.resume()任務啓動.

直接經過SessionDelegate實現代理, 爲何這裏還要有一個DataTaskDelegate, 真是費勁呢。

首先,要明白要SessionDelegate是全部 Session 的代理遵循者,任何的代理都會來到這裏響應,而DataTaskDelegate 是具體任務的實現者,這裏面全部方法都是由 SessionDelegate 下發響應的。(一個下發任務,一個具體幹活)

下面給我一首歌的時間🎤🎤🎤來看一下SessionDelegate.swiftURLSessionDownloadDelegate的源碼🌰:

從標紅部分能夠看出, self[downloadTask]就等同於 DownloadRequestDownloadRequest.delegate 就等同於 DownloadTaskDelegate.這裏把 downloadTask交給了 DownloadTaskDelegate.urlSession去執行,若是再跟進去源碼 DownloadTaskDelegate.urlSession,就會發現執行的就是具體的 Download操做。

總結

SessionManagerRequest 方法中,表面上看是由SessionManager直接處理了request,然而實際上,是經過SessionManager的代理響應SessionDelegate,而後SessionDelegate把這個具體Request分發給了具體的DataTaskDelegate,而後DataTaskDelegate來執行具體的任務內容。之因此這麼作,是由於SessionDelegate 經過的任務分發,讓處理具體任務的taskdelegate 去處理對應的事務,避免了其內部邏輯混亂和代碼冗餘,實現任務邏輯下沉。關於Request還有不少內容的哦,後面再作補充,若有錯誤,還望大佬們指正。

相關文章
相關標籤/搜索