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

由于AFNetworking本質(zhì)上是對(duì)NSURLConnection和NSURLSession進(jìn)行了封裝設(shè)計(jì),作為一個(gè)優(yōu)秀網(wǎng)絡(luò)請(qǐng)求框架,必然對(duì)多線程這一塊的處理有自己的良好設(shè)計(jì),本文分別探究2.0和3.0時(shí)代對(duì)于多線程的設(shè)計(jì)方案


AFNetworking 2.0

對(duì)于2.0時(shí)代,框架采用了NSURLConnection+NSOperation的模型,那么來(lái)分析一下AF是如何進(jìn)行請(qǐng)求的管理,以及回調(diào)的處理的,我們嘗試列出幾種方案:

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

AF的3.0時(shí)代進(jìn)行了大改動(dòng),其內(nèi)部實(shí)現(xiàn)從基于NSURLConnection變成了NSURLSession,在3.0的設(shè)計(jì)思路這這篇文章中解析了3.0是如何對(duì)NSURLSession進(jìn)行封裝的,這里我們直接看一下對(duì)應(yīng)的源碼:

    self.operationQueue = [[NSOperationQueue alloc] init];
    self.operationQueue.maxConcurrentOperationCount = 1;
    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
  • 3.0以AFURLSessionManager為核心類,每個(gè)對(duì)象都擁有一個(gè)NSOperationQueue用于請(qǐng)求發(fā)送和回調(diào)管理(可以發(fā)現(xiàn)是一個(gè)串行隊(duì)列)
  • 如果要轉(zhuǎn)化為NSURLSession,那么就相當(dāng)于每個(gè)session擁有一個(gè)NSOperationQueue,然后一個(gè)session可以創(chuàng)建多個(gè)任務(wù),這些任務(wù)是在串行隊(duì)列中執(zhí)行
總結(jié)

之所以設(shè)計(jì)方式不同了,有原因來(lái)自:2.0時(shí)代的NSURLConnection是一個(gè)全局的設(shè)計(jì),從調(diào)用方式也能發(fā)現(xiàn):

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進(jìn)行了分離,可以從使用看出:

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

這樣的設(shè)計(jì)就能夠?yàn)槊總€(gè)session對(duì)象(AFURLSessionManager對(duì)象)添加獨(dú)自的操作隊(duì)列NSOperationQueue,分別進(jìn)行各自的請(qǐng)求發(fā)送和回調(diào)管理。而2.0中使用全局設(shè)計(jì),因此AF維護(hù)一條子線程專門用于管理所有的請(qǐng)求發(fā)送和回調(diào)處理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容