前言
Alamofire在5.0進(jìn)行一次重構(gòu),現(xiàn)在還未正式發(fā)布,下面的分析都基于5.0.0-rc.3版本
問(wèn)題
在進(jìn)入正文之前,先看下下面這幾個(gè)問(wèn)題,希望你看完這篇文章,能回答以下問(wèn)題?
- Session,SessionDelegate,Request它們之間的關(guān)系?
let urlString = "https://api.apiopen.top/getJoke?page=1&count=2&type=text"
let request = AF.request(urlString).responseJSON { (resp) in
print(resp)
}
//假設(shè)請(qǐng)求3秒之后就回來(lái)了
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
request.responseJSON { (resp) in
print(resp)
}
}
- 都知道Alamofire是對(duì)URLSession的封裝,上面那段代碼,DataTask是什么時(shí)候創(chuàng)建的,又是什么發(fā)送的?
- 在請(qǐng)求回來(lái)之后,再多次設(shè)置響應(yīng),是否能進(jìn)行回調(diào)?
- responseJSON里面都做了些什么事?
Alamofire中主要的類或協(xié)議圖
image
Session,SessionDelegate,Request,RequestDelegate主要屬性介紹
Session屬性:
- let session: URLSession,系統(tǒng)的URLSession,用于創(chuàng)建task
- let delegate: SessionDelegate,session的代理,用于處理請(qǐng)求的各種回調(diào)
- let startRequestsImmediately: Bool,是否立即發(fā)出請(qǐng)求
- let rootQueue: DispatchQueue,內(nèi)部的回調(diào)和狀態(tài)更新所處的隊(duì)列,必須是串行隊(duì)列
- let requestQueue: DispatchQueue,創(chuàng)建Request所在的隊(duì)列,默認(rèn)是target為rootQueue的串行隊(duì)列
- let serializationQueue: DispatchQueue,反序列化Response數(shù)據(jù)時(shí)所在的隊(duì)列,默認(rèn)是target為rootQueue的串行隊(duì)列
- let interceptor: RequestInterceptor?,request攔截器,是RequestAdapter和RequestRetrier的合并,用于在發(fā)送請(qǐng)求之前修改Request和請(qǐng)求失敗之后的重試策略
- let serverTrustManager: ServerTrustManager?,安全認(rèn)證管理者
- let redirectHandler: RedirectHandler?,重定向的回調(diào)
- let cachedResponseHandler: CachedResponseHandler?,緩存的回來(lái)
- let eventMonitor: CompositeEventMonitor,事件監(jiān)聽(tīng)器
- var requestTaskMap:RequestTaskMap,用于存放task、request以及task的狀態(tài)
- var activeRequests:Set<Request> = [],用于所有活躍的request
SessionDelegate屬性:
- private let fileManager: FileManager,用于下載的回調(diào)里,處理文件
- weak var stateProvider: SessionStateProvider? ,用于在URLSessionDelegate獲取request信息以及回調(diào)給外面狀態(tài)
- var eventMonitor: EventMonitor?,在各種回調(diào)里,調(diào)用事件監(jiān)聽(tīng)器對(duì)應(yīng)的方法,讓外界處理
SessionStateProvider協(xié)議定義的方法:
- var serverTrustManager: ServerTrustManager? { get }獲取安全認(rèn)證管理者
- var redirectHandler: RedirectHandler? { get }獲取重定向的處理者
- var cachedResponseHandler: CachedResponseHandler? { get }獲取緩存響應(yīng)的處理者
- func request(for task: URLSessionTask) -> Request?通過(guò)task獲取Request
- func didGatherMetricsForTask(_ task: URLSessionTask)收集到性能指標(biāo)之后的回調(diào)
- func didCompleteTask(_ task: URLSessionTask)請(qǐng)求完成的回調(diào)
- func credential(for task: URLSessionTask, in protectionSpace: URLProtectionSpace) -> URLCredential?獲取身份驗(yàn)證的證書(shū)
- func cancelRequestsForSessionInvalidation(with error: Error?),URLSession無(wú)效的回調(diào)
Request屬性:
- let underlyingQueue: DispatchQueue,內(nèi)部回調(diào)的異步串行隊(duì)列
- let serializationQueue: DispatchQueue,序列化所在的隊(duì)列,同Session
- let eventMonitor: EventMonitor?,事件監(jiān)聽(tīng)器,同Session
- let interceptor: RequestInterceptor?,request攔截器,同Session
- weak var delegate: RequestDelegate?,requestDelegate
- protectedMutableState: Protector<MutableState>,存放著request的各種信息
- state狀態(tài)
- uploadProgressHandler上傳的進(jìn)度回調(diào)
- downloadProgressHandler下載的進(jìn)度回調(diào)
- redirectHandler重定向的回調(diào)
- cachedResponseHandler緩存的回調(diào)
- cURLHandler,curl的回調(diào)
- responseSerializers,響應(yīng)序列化的集合
- responseSerializerCompletions,響應(yīng)序列化回調(diào)的集合
- requests,當(dāng)前請(qǐng)求所有的request
- tasks,當(dāng)前請(qǐng)求所有的task
- metrics,當(dāng)前請(qǐng)求所有的指標(biāo)
- retryCount,已經(jīng)重試的次數(shù)
- 錯(cuò)誤信息
- 其他屬性都間接或這屆的依賴于protectedMutableState
RequestDelegate協(xié)議定義的方法:
- var sessionConfiguration: URLSessionConfiguration { get },獲取Session配置
- var startImmediately: Bool { get },是否立即發(fā)送請(qǐng)求
- func cleanup(after request: Request),此次請(qǐng)求已結(jié)束,清除此次請(qǐng)求
- func retryResult(for request: Request, dueTo error: AFError, completion: @escaping (RetryResult) -> Void),詢問(wèn)代理是否需要重試
- func retryRequest(_ request: Request, withDelay timeDelay: TimeInterval?),告訴代理在多久之后重試
Session,SessionDelegate,Request之間的關(guān)系
image
- Session創(chuàng)建之后會(huì)創(chuàng)建URLSession,此時(shí)Session.delegate和URLSession.delegate都指向SessionDelegate的實(shí)例
- Session.delegate指向SessionDelegate是為了持有它,不讓他釋放,URLSession.delegate指向它,是讓它執(zhí)行URLSession以及URLSessionTask的各種回調(diào)
- SessionDelegate.stateProvider會(huì)指向Session
- 當(dāng)調(diào)用Session.request方法之后,會(huì)創(chuàng)建Request,并把Request放入Session.activeRequests中
- Request.delegate會(huì)指向Session
Request的創(chuàng)建流程圖
image
根據(jù)此流程圖回答上面的問(wèn)題
- dataTask是在
Session.didCreateURLRequest中創(chuàng)建的,由于創(chuàng)建完Request,無(wú)論是操作Request還是response函數(shù)內(nèi)部操作都是異步,執(zhí)行順序無(wú)法確定,所以發(fā)送請(qǐng)求有可能在這2個(gè)地方,一是Session.updateStatesForTask,二是在Request.resume函數(shù)中 - 在請(qǐng)求回來(lái)之后,再多次設(shè)置響應(yīng),從上面的流程圖可以看出,會(huì)直接調(diào)用回調(diào)
- response中除了做了流程圖內(nèi)的事之外,在執(zhí)行回調(diào)之前,會(huì)先把data反序列化對(duì)應(yīng)的格式,若序列化失敗,會(huì)調(diào)用代理來(lái)詢問(wèn)是否需要重試,若反序列化成功,則調(diào)用回調(diào)
Request請(qǐng)求完成之后到調(diào)用響應(yīng)回調(diào)的流程圖
image