AFNetworking源碼——多線程(2.0 & 3.0)

由于AFNetworking本質上是對NSURLConnection和NSURLSession進行了封裝設計,作為一個優秀網絡請求框架,必然對多線程這一塊的處理有自己的良好設計,本文分別探究2.0和3.0時代對于多線程的設計方案


AFNetworking 2.0

對于2.0時代,框架采用了NSURLConnection+NSOperation的模型,那么來分析一下AF是如何進行請求的管理,以及回調的處理的,我們嘗試列出幾種方案:

  • 所有請求都在主線程中發送,并且回調處理也有主線程來完成
    這應該是最直接的方式,那我們來看下這個方式有什么不好的地方
    • 如果請求數量很多,那么主線程會消耗大量的CPU資源來做請求的發送和回調的處理,對于這么注重流暢度的iOS,該方法直接被淘汰了
  • 開啟一條子線程,在子線程中進行請求的同步發送,并且等待回調
    利用子線程做處理,就不會有上述問題,但是仍然存在一些不好的地方
    • 子線程由于需要接受回調,所以需要使用runLoop進行線程保活,這樣即使回調完成,線程資源仍然得不到釋放,如果請求數量很多,就意味著開辟很多條子線程,造成大量的資源浪費
  • AF的方案:啟用一個子線程,異步發送請求,處理回調事件
    通俗來說,就是開辟一條專門用于請求管理的線程,下面為2.0中的源碼
[self performSelector:@selector(operationDidStart)
              onThread:[[self class] networkRequestThread]          withObject:nil
         waitUntilDone:NO
                 modes:[self.runLoopModes allObjects]]
AFNetworking 3.0

AF的3.0時代進行了大改動,其內部實現從基于NSURLConnection變成了NSURLSession,在3.0的設計思路這這篇文章中解析了3.0是如何對NSURLSession進行封裝的,這里我們直接看一下對應的源碼:

    self.operationQueue = [[NSOperationQueue alloc] init];
    self.operationQueue.maxConcurrentOperationCount = 1;
    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
  • 3.0以AFURLSessionManager為核心類,每個對象都擁有一個NSOperationQueue用于請求發送和回調管理(可以發現是一個串行隊列)
  • 如果要轉化為NSURLSession,那么就相當于每個session擁有一個NSOperationQueue,然后一個session可以創建多個任務,這些任務是在串行隊列中執行
總結

之所以設計方式不同了,有原因來自:2.0時代的NSURLConnection是一個全局的設計,從調用方式也能發現:

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"www.nineteen.me"]];
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * __nullable response, NSData * __nullable data, NSError * __nullable connectionError) {
    // ...
}];

而NSURLSession是將Session和task進行了分離,可以從使用看出:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
                                                      delegate:self
                                                 delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [session dataTaskWithURL:[[NSURL alloc]initWithString:@""]];
[task resume];

這樣的設計就能夠為每個session對象(AFURLSessionManager對象)添加獨自的操作隊列NSOperationQueue,分別進行各自的請求發送和回調管理。而2.0中使用全局設計,因此AF維護一條子線程專門用于管理所有的請求發送和回調處理。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容