架构之路 (三) —— APP架构之网络层分析(一)

版本记录

版本号 时间
V1.0 2018.05.19

前言

前面写了那么多篇主要着眼于局部问题的解决,包括特定功能的实现、通用工具类的封装、视频和语音多媒体的底层和实现以及动画酷炫的实现方式等等。接下来这几篇我们就一起看一下关于iOS系统架构以及独立做一个APP的架构设计的相关问题。感兴趣的可以看上面几篇。
1. 架构之路 (一) —— iOS原生系统架构(一)
2. 架构之路 (二) —— APP架构分析(一)

回顾

上一篇主要讲述了一个APP的架构分析和设计,这一篇我们就说一下APP架构中的网络层。


网络层在APP中的地位

网络层就是APP从服务器获取信息的一个媒介和方式,没有网络层,可以说APP就是一潭死水,有没有没有网络层的APP存在呢?有,但是很少,比如一些不需要和服务器交互的APP就不需要网络层,比如你做一个简单的相机,带有各种滤镜处理,也不需要注册登录等逻辑,照完像就保存到本地,那么这个APP就不需要网络层,但是极大多数APP都是需要网络层的,有了网络层你的APP才会“动起来”。


casa大牛对网络层搭建的想法

关于网络层的搭建,有很多大神的博客上都说的很多比如,Casa Taloyum的博客。他主要说了三个问题,分别如下所示:

1. 网络层跟业务对接部分的设计

网络层跟业务层对接部分设计的好坏,会直接影响到业务工程师实现功能时的心情。主要是围绕下面三个问题进行阐述的。

使用哪种交互模式来跟业务层做对接

这里其实有两个问题:

  • 以什么方式将数据交付给业务层?

这里casa大神建议使用Delegate为主,Notification为辅,不建议使用block,因为block容易因为循环引用造成对象无法释放,在网络回调中使用block,是block导致对象生命周期被延长的其中一个场合,当ViewController从window中卸下时,如果尚有请求带着block在外面飞,然后block里面引用了ViewController(这种场合非常常见),那么ViewController是不能被及时回收的,即便你已经取消了请求,那也还是必须得等到请求着陆之后才能被回收。然而使用delegate就不会有这样的问题,delegate是弱引用,哪怕请求仍然在外面飞,ViewController还是能够及时被回收的,回收之后指针自动被置为了nil,无伤大雅。

casa建议使用Notification使用情景在于网络层网络状况变化的情况,例如2G到3G等方式的变化。

  • 交付什么样的数据给业务层?

网络层数据交付这部分时,casa添加了reformer(名字而已,叫什么都好)这个对象用于封装数据转化的逻辑,这个对象是一个独立对象,事实上,它是作为Adaptor模式存在的。我们可以这么理解:想象一下我们洗澡时候使用的莲蓬头,水管里出来的水是API下发的原始数据。reformer就是莲蓬头上的不同水流挡板,需要什么模式,就拨到什么模式。

是否有必要将API返回的数据封装成对象然后再交付给业务层

作者的意见是需要将API返回的数据封装成对象,在交给业务层的。

使用集约化调用方式还是离散型调用方式去调用API

集约型API调用其实就是所有API的调用只有一个类,然后这个类接收API名字,API参数,以及回调着陆点(可以是target-action,或者block,或者delegate等各种模式的着陆点)作为参数。然后执行类似startRequest这样的方法,它就会去根据这些参数起飞去调用API了,然后获得API数据之后再根据指定的着陆点去着陆。

集约型API调用方式:
[APIRequest startRequestWithApiName:@"itemList.v1" params:params success:@selector(success:) fail:@selector(fail:) target:self];

离散型API调用是这样的,一个API对应于一个APIManager,然后这个APIManager只需要提供参数就能起飞,API名字、着陆方式都已经集成入APIManager中。比如这样:

离散型API调用方式:
@property (nonatomic, strong) ItemListAPIManager *itemListAPIManager;
// getter
- (ItemListAPIManager *)itemListAPIManager
{
    if (_itemListAPIManager == nil) {
        _itemListAPIManager = [[ItemListAPIManager alloc] init];
        _itemListAPIManager.delegate = self;
    }
    return _itemListAPIManager;
}
// 使用的时候就这么写:
[self.itemListAPIManager loadDataWithParams:params];

关于集约型的API调用和离散型的API调用,casa倾向于这样:对外提供一个BaseAPIManager来给业务方做派生,在BaseManager里面采用集约化的手段组装请求,放飞请求,然而业务方调用API的时候,则是以离散的API调用方式来调用。如果你的App只提供了集约化的方式,而没有离散方式的通道,那么我建议你再封装一层,便于业务方使用离散的API调用方式来放飞请求。

2. 网络层的安全机制实现

  • 判断API的调用请求是来自于经过授权的APP
  • 保证传输数据的安全
    • 建议使用HTTPS

3. 网络层的优化方案

网络层的优化手段主要从以下三方面考虑:

针对链接建立环节的优化

  • 使用缓存手段减少请求的发起次数
  • 使用策略来减少请求的发起次数

针对链接传输数据量的优化

传输的数据少了,那么自然速度就上去了。这里没什么花样可以讲的,就是压缩呗。

针对链接复用的优化

建立链接本身是属于比较消耗资源的操作,耗电耗时。SPDY自带链接复用以及数据压缩的功能,所以服务端支持SPDY的时候,App直接挂SPDY就可以了。如果服务端不支持SPDY,也可以使用PipeLine,苹果原生自带这个功能。


网络层规范

这里另外一个牛人写的也不错,先把地址贴出来 —— iOS网络层架构设计分享

1. 网络层接口规范

接口数据返回结构

返回的是两层三部分结构code、msg、data

"code": 0,
"msg": "",
"data": {
        "upload_log": true,
        "has_update": false,
        "admin_id": "529ecfd64"
    }
  • code:错误码,这个用来定义各种错误原因,方便客户端进行各种处理。
  • msg:接口文案提示,包括错误提示,用来直接显示给用户。
  • data:需要返回的数据,可以是字典,可以是数组。

关于请求方式

一般都提供标准的GET/POST请求方式。

2. 多服务器多环境设置

为什么要多服务器环境?标准的APP是有4个环境的,开发、测试、预发、正式,特别是服务器的代码,不能说所有的代码更改都在正式环境下。

3. 网络请求的取消

当一个页面的请求正在天上飞的时候,用户等了好久不耐烦了,小手点了个back,然后ViewController被pop被回收。此时请求的着陆点就没了。这是很危险的情况,着陆点要是没了,就很容易crash的。

一般是按照下面方式进行处理:使用了runtime,给ViewController添加一个字典,来保存requestID和BaseDataEngine,这样对于ViewController来说就不是必须要写变量来持有BaseDataEngine了。

在发起请求的时候进行绑定

[control.networkingAutoCancelRequests setEngine:self requestID:self.requestID];

在请求完成的时候进行删除

[weakControl.networkingAutoCancelRequests removeEngineWithRequestID:engine.requestID];

我自己关于网络层架构的看法

  • 现在绝大多数APP都不会自己封装NSURLSession进行网络下载,基本都是基于AFNetworking的二次开发的。因此,很多关于网络的问题,转化为了对AFNetworking进行二次封装的优劣的问题。我待过的公司,我见过封装后用delegate回调数据的,也见过用block回调数据的,他们各有优劣。用deleagate回调数据的,可以说很麻烦,代码很分散,你要在请求的VC里面设置delegate,还有实现代理方法,优点就是弱引用,不会引起循环引用造成VC释放了,请求还在飞的情况。block代码就比较集中了,处理起来很简明,但是容易引起retain,这个是需要注意的问题。

  • 对于AFNetworking的二次封装,建议抽象出一个BaseService,然后业务方根据不同host和需求应用场景,分离出自己的service子类,然后请求和链接网络层。

  • 关于网络层回来的数据,我建议也是采用reformer的形式比较好,根据不同的需求可以直接返回不同的数据,只需更改淋浴的出水口的莲蓬头就可以出不同形式的水。

参考文章

1. iOS应用架构谈 网络层设计方案
2. iOS网络层架构设计分享
3. iOS网络架构文档整理
4. iOS网络架构文档整理

你可能感兴趣的:(架构之路 (三) —— APP架构之网络层分析(一))