首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

iOS开发:关于Moya之上的Request层

  • 25-04-22 20:22
  • 4364
  • 7734
juejin.cn

我遇到的问题

我在做项目开发的时候,遇到了这样两个页面:

  • A页面是一个关注列表页面,有列表接口与关注与取消关注接口
  • B页面是一个他人主页页面,有他人信息接口与关注与取消关注接口

可以看到,这两个页面都会用到关注与取消关注接口:

画板

一般1个ViewController会对应1个ViewModel,而ViewModel可能会对应多个网络请求:

画板

如果我们项目简单,直接多个网络请求放在一个ViewModel中,没有问题。

但是随着项目的复杂度增加,我们可能会遇到这样的问题:ViewModel中有多个网络请求,而其中某个或者某个网络请求可能会在多个ViewModel中复用。

使用继承可以吗?

有人可能会思考,那么就将业务复用接口写到一个基类ViewModel中继承即可,比如下面这样的伪代码:

swift
代码解读
复制代码
class 他人主页ViewModel: 关注列表ViewModel { /// 新写一个他人信息接口 }

那么此时,他人主页ViewModel实际上包含了3个接口:

  • 列表接口 (我们不需要)
  • 关注与取消接口
  • 他人信息接口

显然,这样业务耦合了,并且他人主页中出现了我们不需要使用的列表接口!

通过类的继承,明显无法满足每一个接口都独立并且解耦,因为Swift是单继承关系。

换个角度

既然class的类继承不行,我们可以试试使用protocol。

protocol可以多继承,而且protocol可以被多个类遵循,这样的话,我只需要将每个一个接口都通过protocol来定义与实现。

于是我先定义了一个空协议BaseRequestable,然后每个网络请求都定义一个协议,并且继承BaseRequestable协议,并在extension中进行实现:

swift
代码解读
复制代码
/// 基类协议,让其他业务请求都继承这个协议,如此一来,万一需要as?进行转换留余地 protocol BaseRequestable {} /// 列表接口 protocol ListRequest: BaseRequestable { func requestList() -> Single<Moya.Response> } extension ListRequest { func requestList() -> Single<Moya.Response> { homeProvider.rx.request(HomeService.list) } } /// 他人主页接口 protocol OtherInfoRequest: BaseRequestable { func requestOtherInfo() -> Single<Moya.Response> } extension OtherInfoRequest { func requestOtherInfo() -> Single<Moya.Response> { homeProvider.rx.request(HomeService.otherInfo) } } /// 关注与取消接口 protocol AttentionRequest: BaseRequestable { func requestAction(type:ActionType) -> Single<Moya.Response> } extension AttentionRequest { func requestAction(type:ActionType) -> Single<Moya.Response> { homeProvider.rx.request(HomeService.attention(type)) } }

而后不同ViewModel直接将不同的Request当作最小工件装配即可:

swift
代码解读
复制代码
class 关注列表ViewModel: ListRequest, AttentionRequest{ } class 他人主页ViewModel: OtherInfoRequest, AttentionRequest { }

有没有其他的方式?

上面这种思路是将每一个接口都当作一个独立的protocol去实现,虽然解耦的很不错,但是这样写起来有点费手,而且如果一个ViewModel中有5个甚至更多的接口请求,那么就会变成这样:

swift
代码解读
复制代码
class ViewModel: Request1, Request2, Request3, Request4, Request5... { }

如果熟悉前端或者Retrofit自动化生成,你会发现它们会把所有的接口集中放在一起维护:

swift
代码解读
复制代码
protocol RequestProtocol { static func requestList() -> Single<Moya.Response> static func requestOtherInfo() -> Single<Moya.Response> static func requestAction(type:ActionType) -> Single<Moya.Response> } extension RequestProtocol { static func requestList() -> Single<Moya.Response> { homeProvider.rx.request(HomeService.list) } static func requestOtherInfo() -> Single<Moya.Response> { homeProvider.rx.request(HomeService.otherInfo) } static func requestAction(type:ActionType) -> Single<Moya.Response> { homeProvider.rx.request(HomeService.attention(type)) } } enum Request: RequestProtocol {}

不同的ViewModel,根据需要调用这个Request的方法即可:

swift
代码解读
复制代码
class 关注列表ViewModel { func getList() { Request.requestList() } } class 他人主页ViewModel { func getOtherInfo() { Request.requestOtherInfo() } }

这样的好处是所有的接口都集中管理在一个protocol中,减少每个接口一个protocol的维护量,过于分散的问题。

思考与总结

在Request中是否需要进行数据转换?

我理解,网络请求就是一个单一的功能,返回数据即可,而涉及的转换,判断都不应该在这一层进行处理,所以最后返回的结果就是Single或者Moya.Response即可。

Moya与App之间到底应该如何分层?

这个是Moya官方给出的示例图,Moya封装了Alamofire的细节之后,App其实就可以直接调用了:

swift
代码解读
复制代码
import Moya enum HomeService { } extension HomeService: TargetType { } let homeProvider = MoyaProvider<HomeService>(plugins: plugins)

homeProvider其实不管在任何你想要调用的位置都可以使用。

只是,在目前流行的MVVM中,更倾向于将homeProvider在ViewModel中调用罢了,这里我们不过是将ViewModel层中的调用做了更加精细化的处理,这样做的好处是:

  1. 可以将网络请求与ViewModel进行解耦
  2. 可以将网络请求进行复用
  3. 可以将网络请求进行组合
  4. 可以将网络请求进行分层
  5. 可以将网络请求进行单元测试
  6. 可以将网络请求进行Mock

如果去查阅GetX在Flutter中的使用,你会发现,Page与Controller的关系亦是如此,Page只关心页面的构建,所有的逻辑都是Controller中,而在Controller中又将网络请求独立处理,当然这是一个题外话了,我们有空再聊。

注:本文转载自juejin.cn的season_zhu的文章"https://juejin.cn/post/7495675599110996020"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

141
iOS
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top