AFNetworking源码分析

结论:

1、统一网络入口;

2、统一共性处理;

简述

在iOS开发中,与直接使用苹果框架中提供的NSURLConnection或NSURLSession进行网络请求相比,使用AFNetworking会有哪些好处?当同时发起多个网络请求AFNetworking是如何实现并发的,在并发的时候,AFNetworking是如何管理线程的?苹果重构NSURLConnetion推出新的网络加载系统NSURLSession解决了什么问题或者是与NSURLConnection相比NSURLSession有好些好处?上面问题的答案会贯穿在这篇文章中(本篇文章只涉及了与操作队列,多线程相关的分析)。

不用网络框架进行网络请求

NSURLConnection的简单使用(下面的代码均只为了演示,更详细的使用方法请自行谷歌)

NSURLConnection提供了两个类方法用于发起同步或异步请求,对于异步请求来说必然是在子线程中发起,若在主线程中发起异步网络请求会造成主线程阻塞,界面无响应,这就涉及到多线程编程。但多线程编程是一门非常细致的活,要考虑很多的问题,比如线程的生命周期,多线程资源竞争,加锁,避免死锁,稍不留意就会踩到坑里。好在苹果的接口使用极其方便,你甚至不需要理解多线程就能轻松使用上多线程了,发起异步请求的接口内部已经实现了多线程相关的操作。越是高级的接口,其隐藏的细节就越多,对于开发者来说当然是很方便,但若还能对其实现有所理解那就更完美了。当子线程发起了异步请求后会阻塞以等待网络响应,那应该由谁来处理网络响应呢?苹果提供了两种方式,一种是block,提供一个处理响应的block回调。一种是代理,使用代理的话就必须实现NSURLConnectionDelegate这个协议。你只需要在有网络请求的UIViewController中调用NSURLConnection提供的类方法就可以了。但如果你的项目中有不止一个UIViewController或者有的UIViewController中都不止一个请求的话,你就需要在每一个有网络请求的UIViewController中这样写。这样写会有什么问题呢?首先会造成软件结构不清晰,没有剥离出网络层,其次没有实现网络请求统一管理,无法实现取消所有网络请求等功能,再有会出现很多重复的代码,没有让公用功能形成模块,进行复用。当然为了解决这些问题你也可以自己实现自己的网络框架。

使用NSURLConnection版本的AFNetworking

使用网络框架的好处在于可以将分散在各个视图控制器中的网络请求统一起来模块化形成网络层,降低与数据层和表现层的耦合。AFNetworking就做了这样的工作。网络上已经有很多分析基于NSURLConnection实现的AFNetworking 2.x的源代码,这里只简单说一下其实现整个流程,想要深入了解的请谷歌或查看其源代码。首先AFNetworking要解决实现接口统一和所有网络请求统一管理的问题。NSURLConnection发起有两种方式发起请求,分别是设置响应block和代理,那采用哪种方式能够实现网络请求统一管理呢?block肯定不行,因为传入响应回调block的[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]方法会立即执行。那么只能使用设置响应代理这种方式了。具体实现是将网络请求继承于NSOperation,生产网络请求,然后再将这个网络请求加入操作队列里,剩下的所有与线程相关的操作都由这个操作队列去实现。越高级易容的接口就隐藏越多的实现细节,NSOperation隐藏了线程相关的所有细节,使得开发者只需关心构建什么样的操作。AFNetworking甚至隐藏了操作,操作队列的概念,使得开发者只需关心如何设置网络相关的请求参数,响应回调等,而不用再关心当多个网络请求如何进行统一管理,这些都已经由AFNetworking内部的操作队列属性完成了。那需要为每个请求创建一个线程来发起请求吗?基于NSURLConnection的AFNetworking是只创建了一条线程来发起所有请求并阻塞以等待响应。

重构推出的NSURLSession解决了NSURLConnection哪些问题

从2013年苹果发布重构后的加载系统NSURLSession,AFNetworking这个最受欢迎的网络框架也随之发布了基于NSURLSession的实现版本。这篇文章从 NSURLConnection 到 NSURLSession对NSURLSession的使用做了介绍。既然是对NSURLConnection进行的重构,那一定是解决了NSURLConnection存在的一些问题。苹果的接口以及其简单的形式呈现给开发者,尽量把复杂,容易出错的地方以简单的接口暴露出来,这使得用户能够参考文档很快上手,但这也有一些弊端,就是开发者对其中的原理不是很了解。越高级的接口越容易使用,但其隐蔽的实现细节就越多。相信在进行多线程编程的时候,很多开发者遇到过各种各样的坑,但在iOS平台上,苹果推出了GCD,NSperation等一系列接口可以让开发者完全可以只关注业务的实现,这些接口内部已经替开发者管理好了线程的创建,销毁,多线程资源竞争等需要开发者费很多精力的事情,甚至开发者不用对多线程理解透彻都能把多线程用得得心应手。NSURLConnection已经隐藏了线程相关的操作,已经给开发者减轻了很多负担。但NSURLConnectoin只隐藏了单个网络请求的线程的相关操作,并没有提供接口来解决多个网络请求时多个线程的管理问题,譬如当有多个网络请求时是否应该使用线程池来避免不停创建与销毁线程(这个可以有NSOperationQueue很好的解决)。并且NSURLConnection不是基于HTTP/2协议的,若使用NSURLConnection发起请求则每次请求都需要经过三次握手过程,可见NSURLConnection确实有很多可以优化的地方(我只发现这些)。NSURLConnection存在的无法将多个请求关联起来的问题已经很好的由AFNetworking解决了,所以推出的NSURLSession可以说是借鉴了AFNetworking的思想,并且可以从AFNetworking的源代码中很容易的看出来。基于NSURLConnection的AFNetworking需要让网络请求继承与NSOperation,然后再将该生成的网络请求加入操作队列中,但基于NSURLSessioin的AFNetworking只需要创建一个网络请求任务就可以了,原因在于,NSURLSession内部已经维护了两个操作队列,一个是处理session的相关回调,一个是处理响应相关的回调,所以说NSURLSession是借鉴了AFNetworking的继承于NSOperation和用单线程发起并等待响应的思想(这个会在后面给出证明)。

基于NSURLSession的AFNetworking的源码分析

下图是基于NSURLSession的AFNetworking的UML图(只为展示类之间的关联关系,并没有给出每个类的所有属性和方法):

 
AFNetworking.png

从该类图已经能够明白AFNetworking整个的工作流程。



作者:zongmumask
链接:https://www.jianshu.com/p/8eac5b1975de
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

原文地址:https://www.cnblogs.com/feng9exe/p/8575742.html