Moya 源码分析
面向协议编程
OOP 带来的三个问题
- 横切关注点
- 菱形缺陷
- 动态派发的安全性
面向协议参考文章
Moya简单介绍和使用
Moya是一个基于Alamofire开发的,轻量级的Swift网络层。Moya的可扩展性非常强,可以方便的RXSwift等函数式框架结合。
简单使用
|
|
框架组成
Moya的项目主要由八个部分组成。
request
request部分主要包含请求相关的代码。定义了TargetType协议,通过targetType 来定义一个请求
- TargetType: 请求相关信息
- Endpoint: Moya进行请求的最终数据结构
- Task: 定义了请求的发起方式,请求参数设置等
- Cancellable: 请求取消用
Provider
Provider中包含了最核心的代码,主要负责组装 TargetType 和 Endpoint,并发起请求和转换请求结果为Response
- MoyaProvider: 主要的核心代码
- MoyaProvider+Defaults: 提供一些内部需要的默认实现
- MoyaProvider+Internal: 提供了内部使用的方法
response
响应结果相关方法,以及字典,JSON等相关转换方法
- MoyaError: 封装了相关错误
- Response: 核心响应体类
Plugins
插件相关。
- Plugin: 插件核心定义,用于扩展其他插件
- AccessTokenPlugin: 授权插件
- NetworkActivityPlugin: 显示网络活动插件(转圈小菊花靠这个来显示)
- NetworkLoggerPlugin: 像控制台输出日志的插件
- CredentialsPlugin: https证书交换插件
Alamofire
Alamofire 的封装层
- MultipartFormData: 表单数据的封装
- Moya+Alamofire: Alamofire类型桥接
utils
工具类
Extension
其他框架的扩展支持,目前主要就是ReativeCocoa和RxSwift的扩展
test
单元测试相关
TargetType
|
|
TargetType协议定义了调用方需要实现哪些属性,来提供一个请求所需要的值。
Provider
Providers是Moya中的核心,Moya中所有的API请求都是通过Provider来发起的。因此大多数时候,你的代码请求像这样:
|
|
Provider 真正在做的事情可以用一个流来表示: Target -> Endpoint -> Request .这个过程中 Provider会一步步来生成一个NSURLRequest来交给Alamofire发起请求.
下面我们从Provider的构造函数开始来看一看这个类的组成
|
|
首先我们可以看到三个闭包,这三个闭包我们放到最后说。
- 首先一个callbackQueue,如字面意思,回调的线程。
- manager: manager是最终真正用来请求的类,是由Alamofire桥接过来的。Moya只对Alamofire的类型进行了简单的桥接,这样做的好处是,如果调用方不使用Alamofire的话,我们可以快速替换网络请求库,moya提供了一个默认的Manager实现
|
|
- plugins: 需要使用到的插件,这是一个非常方便的功能,能保证在不修改源码的情况下,来扩展其他功能。而且能够保证Provider的职责单一,满足开闭原则。
- trackInFlights: 是否要追踪请求。这个默认是不追踪的。如果传入true的话,
接下来是最核心的三个闭包
- EndpointClosure: 这个closure负责从TargetType转换成Endpoint, EndPoint 是最终发起请求的一个数据格式,保存了下面数据
|
|
从初始化方法中我们可以看到,Moya 对于 EndpointClosure 提供了默认实现,我们可以在MoyaProvider+Defaults.swift 中找到它
|
|
我们可以看到这里只是一个简单的转换,在实际使用过程中,很多情况下我们需要自定义这个闭包来实现更复杂的功能
- requestClosure:负责把Endpoint 转换成 NSURLRequest,同样的我们可以在 MoyaProvider+Defaults.swift 中找到它
|
|
- stubClosure: 这个闭包会返回一个枚举 StubBehavior , 默认会返回never,如果你需要假数据测试的话可以重写这里。
|
|
Moya采取了最简单粗暴的方式来返回假数据.如果是never 则进行真正的请求。否则直接进入假数据部分.
MoyaProvider+Internal.swift
|
|
Manager和Alamofire
Moya在 Moya+Alamofire.swift 文件中对 Alamofire进行了简单的包装,这一层包装隔离了Alamofire的代码,如果需要更换请求框架的话,可以进行简单的修改来替换,而不必修改外部调用。
如果你想创建自己的Manager的话,可以在Provider初始化的时候传入自己的Manager
Plugin
Moya提供了非常好用的插件机制,通过插件你可以在不修改源码的基础上,充分的扩展Moya的功能。
|
|
调用方可以通过实现上面协议,来创建各种插件处理不同事情,从而保证Provider的单一职责。
- func prepare(_ request: URLRequest, target: TargetType) -> URLRequest 方法会在Endpoint生成Request之前调用。
|
|
- func willSend(_ request: RequestType, target: TargetType) 方法会在发送Alamofire请求之前调用
|
|
func didReceive(_ result: Result
, target: TargetType) 收到Response的时候调用func process(_ result: Result
, target: TargetType) -> Result 请求完成后调用。
Extension
Moya 默认提供了 ReactiveCocoa的扩展ReactiveMoya 和 RxSwift扩展RxMoya。 这里简单看一下RxMoya的实现。
首先我们可以看到三个关于RxMoya的文件
- MoyaProvider+Rx.swift 主要的扩展文件
- Observable+Response.swift Response部分的扩展
- Single+Response.swift Single Response部分的扩展
|
|