前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >架构之路 (三) —— APP架构之网络层分析(一)

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

原创
作者头像
conanma
修改2021-09-06 10:08:26
8390
修改2021-09-06 10:08:26
举报
文章被收录于专栏:正则正则

回顾

上一篇主要讲述了一个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数据之后再根据指定的着陆点去着陆。

代码语言:javascript
复制
集约型API调用方式:
[APIRequest startRequestWithApiName:@"itemList.v1" params:params success:@selector(success:) fail:@selector(fail:) target:self];

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

代码语言:javascript
复制
离散型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

代码语言:javascript
复制
"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了。

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

代码语言:javascript
复制
[control.networkingAutoCancelRequests setEngine:self requestID:self.requestID];

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

代码语言:javascript
复制
[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网络架构文档整理

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 回顾
  • 网络层在APP中的地位
  • casa大牛对网络层搭建的想法
  • 网络层规范
    • 1. 网络层接口规范
      • 2. 多服务器多环境设置
        • 3. 网络请求的取消
        • 我自己关于网络层架构的看法
        • 参考文章
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档