preface

Alamofire was refactoring in 5.0 and has not been released yet. The analysis below is based on version 5.0.0-RC.3

The problem

Before you get into the text, here are a few questions that I hope you’ll be able to answer by the end of this passage.

  1. Session, SessionDelegate, Request?
let urlString = "https://api.apiopen.top/getJoke? page=1&count=2&type=text"
let request = AF.request(urlString).responseJSON { (resp) in
    print(resp)} / / assume the request will be back after 3 seconds DispatchQueue. Main. AsyncAfter (deadline: now () + 10) {request. ResponseJSON {(resp)in
        print(resp)
    }
}
Copy the code
  1. When was the DataTask created? What was the DataTask sent?
  2. After the request comes back, set the response several times. Can you call back?
  3. What’s going on in responseJSON?

The main class or protocol diagram in Alamofire

Session, SessionDelegate, Request, and RequestDelegate properties are described

The Session attributes:
  1. Let session: URLSession, system URLSession, used to create tasks
  2. Let delegate: SessionDelegate, the session delegate that handles various callbacks for requests
  3. Let startRequestsImmediately: Bool, whether the request immediately
  4. Let rootQueue: DispatchQueue, queue on which internal callbacks and status updates are placed, must be serial queues
  5. Let requestQueue: DispatchQueue, create a Request queue, default is a serial queue whose target is rootQueue
  6. Let serializationQueue: DispatchQueue, the queue in which Response data is deserialized. The default is a serial queue whose target is rootQueue
  7. let interceptor: RequestInterceptor? , a request interceptor, which is a merging of the RequestAdapter and RequestRetrier, is used to modify the request retry policy before sending the request and after the request fails
  8. let serverTrustManager: ServerTrustManager? , safety certification manager
  9. let redirectHandler: RedirectHandler? , redirect the callback
  10. let cachedResponseHandler: CachedResponseHandler? , cache back
  11. Let eventMonitor: CompositeEventMonitor, event listener
  12. Var requestTaskMap: requestTaskMap, used to hold the task, the request and the status of a task
  13. Var activeRequests:Set = [], for all activeRequests
SessionDelegate attributes:
  1. Private let fileManager: fileManager is used to process files in the callback for download
  2. weak var stateProvider: SessionStateProvider? To obtain request information from the URLSessionDelegate and to call back to the outside state
  3. var eventMonitor: EventMonitor? In various callbacks, call the method corresponding to the event listener and let the outside world handle it
The SessionStateProvider protocol defines the following methods:
  1. var serverTrustManager: ServerTrustManager? {get} Obtain security certification administrator
  2. var redirectHandler: RedirectHandler? {get} Gets the handler of the redirection
  3. var cachedResponseHandler: CachedResponseHandler? {get} The handler that gets the cached response
  4. func request(for task: URLSessionTask) -> Request? Obtain requests from task
  5. Func didGatherMetricsForTask(_ Task: URLSessionTask) Callback after performance indicators have been collected
  6. Func didCompleteTask(_ Task: URLSessionTask) Callback to request completion
  7. func credential(for task: URLSessionTask, in protectionSpace: URLProtectionSpace) -> URLCredential? Get the certificate for authentication
  8. func cancelRequestsForSessionInvalidation(with error: Error?) , URLSession invalid callback
The Request attributes:
  1. Let underlyingQueue: DispatchQueue, an asynchronous serial queue of internal callbacks
  2. Let serializationQueue: DispatchQueue, which is the queue of the serialization, same as Session
  3. let eventMonitor: EventMonitor? , event listener, same as Session
  4. let interceptor: RequestInterceptor? , request interceptor, same as Session
  5. weak var delegate: RequestDelegate? , requestDelegate
  6. ProtectedMutableState: Protector, which stores various information about the request
    1. State of the state
    2. UploadProgressHandler upload progress callback
    3. DownloadProgressHandler specifies the download progress callback
    4. RedirectHandler Callback for redirection
    5. CachedResponseHandler Callback to the cache
    6. CURLHandler, a callback to curl
    7. ResponseSerializers, collection of response serials
    8. A collection of responseSerializerCompletions, serialization response callback
    9. Requests, all requests are currently requested
    10. Tasks: All tasks are currently requested
    11. Metrics, all metrics currently requested
    12. RetryCount: indicates the number of retries
    13. The error message
  7. All other properties depend indirectly or this time on protectedMutableState
The RequestDelegate protocol defines methods:
  1. Var sessionConfiguration: URLSessionConfiguration {get} to obtain Session configuration
  2. Var startImmediately: Bool {get}, whether to send the request immediately
  3. Func cleanup(after request: request), cleanup of the request
  4. Func retryResult(for Request: Request, dueTo Error: AFError, Completion: @escaping (retryResult) -> Void), asks the agent if it needs to retry
  5. func retryRequest(_ request: Request, withDelay timeDelay: TimeInterval?) , tells the agent how long to retry

Session, SessionDelegate, and Request

  1. Session. Delegate and URLSession. Delegate both point to the instance of SessionDelegate
  2. Session. Delegate points to the SessionDelegate in order to hold it and not to release it, and URLSession. Delegate points to it in order to execute various callbacks to URLSession and URLSessionTask
  3. SessionDelegate stateProvider will point to the Session
  4. When the session. request method is called, the request is created and put into session.activerequests
  5. Request. Delegate points to Session

Request creation flowchart

Follow this flow chart to answer the questions above

  1. DataTask is inSession.didCreateURLRequestSince the Request is created, the internal operations of both Request and response functions are asynchronous, and the execution order cannot be determined, so the Request may be sent in one of the following two placesSession.updateStatesForTaskAnd the second is inRequest. Resume function
  2. After the request comes back, the response is set several more times, and as you can see from the flowchart above, the callback is invoked directly
  3. In response, in addition to the things in the flowchart, data will be deserialized to the corresponding format before the callback is executed. If the serialization fails, the proxy will be called to ask whether it needs to retry; if the deserialization succeeds, the callback will be called

Request Flowchart for calling the response callback after the Request completes