URLSession如何动态控制并发数?

URLSession系列接口对我们的日常开发提供了很大的方便,我们不需要创建和维护队列就可以快速的发起一个网络请求。
但是凡事有利就有弊,封装的越多,我们能够控制的就越少。

起因

最近部门内在对App进行优化,打算将已经使用了五年的网络库从NSURLConnection系列接口切换到URLSession,需要重构。针对弱网的优化也是这次考虑的重点。
因为运营商会控制长连接的连接个数(2G是一个,3G是两个,4G和wifi是四个),所以需要监听网络状态动态的修改URLSession的并发数。

问题

NSURLSession通过NSURLSessionConfiguration传入配置信息并初始化对象。

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;

问题在于NSURLSessionConfiguration在init时是通过深拷贝保存的,即使修改外面对象的HTTPMaximumConnectionsPerHost也无济于事,没法再次修改。

解决方案

为了能够自主控制并发数,只能做一层封装,添加一个请求队列,手动控制并发数。
这里借鉴了AFNetworking中AFImageDownloader的实现。

步骤

  1. 初始化NSURLSession时,NSURLSessionConfiguration的HTTPMaximumConnectionsPerHost设置成 4 (使用 maximumActiveDownloads变量保存初始值,以后通过修改该值控制并发数);
  2. 定义一个成员变量activeRequestCount,计算当前的发起请求的个数,初始值为0;
  3. 每次发起请求前,首先判断当前请求的个数activeRequestCount是否小于maximumActiveDownloads:
- (BOOL)isActiveRequestCountBelowMaximumLimit {
    return self.activeRequestCount <    self.maximumActiveDownloads;
}
  1. 发起请求的方法中进行判断,如何立即请求,activeRequestCount +1,否则保存到数组队列中:
 if ([self isActiveRequestCountBelowMaximumLimit]) {
      [self startMergedTask:mergedTask];
 } else {
      [self enqueueMergedTask:mergedTask];
 }
  ```

5. 请求完成的回调函数中对activeRequestCount -1,并判断是否发起下一次请求:

[strongSelf safelyDecrementActiveTaskCount];
[strongSelf safelyStartNextTaskIfNecessary];
```

这样当我们修改maximumActiveDownloads等于1或者2时,如果当前activeRequestCount 大于等于2,就不会继续发送请求,等到activeRequestCount < maximumActiveDownloads才会发送下个请求。

AFNetworking的源码很值得一读,读的时候可以想想AFNetworking对URLSession是怎样封装的?为什么要这样封装?这样封装的优点是什么?如果让你设计,你会怎么做?

你可能感兴趣的:(URLSession如何动态控制并发数?)