MVVM响应式网络基础架构开源分享给你了~

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: MVVM响应式网络基础架构开源分享给你了~

🧚. RxSwift + Moya + HandyJSON + Plugins.👒👒👒


网络基础架构送给你!!!

基于 RxSwift + Moya 搭建响应式数据绑定网络API架构


MoyaPlugins


该模块主要就是基于moya封装网络相关插件,简单使用注入即可。

目前已封装6款插件供您使用:

Cache:网络数据缓存插件

Loading:加载动画插件

Indicator:指示器插件

Warning:网络失败提示插件

Debugging:调试日志插件

GZip:解压缩插件

🙄 - 简单使用,在API协议当中实现该协议方法,然后将插件加入其中即可:

var plugins: APIPlugins {
    let cache = NetworkCachePlugin(cacheType: .networkElseCache)
    let loading = NetworkLoadingPlugin.init(delayHideHUD: 0.5)
    loading.changeHudCallback = { (hud) in
        hud.detailsLabel.textColor = UIColor.yellow
    }
    return [loading, cache]
}


MoyaNetwork


该模块是基于Moya封装的网络API架构

主要分为以下8部分:

NetworkConfig:在程序最开始处设置配置信息,全局通用

addDebugging:是否开启默认加入调试插件

baseURL:根路径地址

baseParameters:默认基本参数,类似:userID,token等

baseMethod:默认请求类型

updateBaseParametersWithValue:更新默认基本参数数据

RxMoyaProvider:对网络请求添加响应式,返回Observable序列

NetworkUtil:网络相关函数

defaultPlugin:添加默认插件

transformAPIObservableJSON:转换成可观察序列JSON对象

handyConfigurationPlugin:处理配置插件

PluginSubType:继承替换Moya插件协议,方便后序扩展

configuration:设置网络配置信息之后,开始准备请求之前,该方法可以用于本地缓存存在时直接抛出数据而不用再执行后序网络请求等场景


lastNever:最后的最后网络响应返回时刻,该方法可以用于密钥失效重新去获取密钥然后自动再次网络请求等场景

NetworkAPI:在TargetType基础上增加协议属性和封装基础网络请求

ip:根路径地址

parameters:请求参数

plugins:插件数组

stubBehavior:是否走测试数据

retry:请求失败重试次数

request:网络请求方法,返回可观察序列JSON对象

NetworkAPI+ExtNetworkAPI协议默认实现方案

NetworkAPIOO:面向对象转换器,面向协议模式转面向对象,方便习惯OC思维的小伙伴

cdy_ip:根路径地址

cdy_path:请求路径

cdy_parameters:请求参数

cdy_plugins:插件

cdy_testJSON:测试数据

cdy_testTime:测试数据返回时间,默认半秒

cdy_retry:请求失败重试次数

cdy_HTTPRequest:网络请求方法

NetworkX:扩展函数方法等

toJSON:对象转JSON字符串

toDictionary:JSON字符串转字典

+=:字典拼接


🎷 - 面向对象使用示例1:


class OOViewModel: NSObject {
    let disposeBag = DisposeBag()
    let data = PublishRelay<String>()
    func loadData() {
        var api = NetworkAPIOO.init()
        api.cdy_ip = "https://www.httpbin.org"
        api.cdy_path = "/ip"
        api.cdy_method = .get
        api.cdy_plugins = [NetworkLoadingPlugin.init()]
        api.cdy_retry = 3
        api.cdy_HTTPRequest()
            .asObservable()
            .compactMap{ (($0 as! NSDictionary)["origin"] as? String) }
            .catchAndReturn("")
            .bind(to: data)
            .disposed(by: disposeBag)
    }
}


🎷 - MVP使用示例2:


enum LoadingAPI {
    case test2(String)
}
extension LoadingAPI: NetworkAPI {
    var ip: APIHost {
        return NetworkConfig.baseURL
    }
    var path: String {
        return "/post"
    }
    var parameters: APIParameters? {
        switch self {
        case .test2(let string): return ["key": string]
        }
    }
}
class LoadingViewModel: NSObject {
    let disposeBag = DisposeBag()
    let data = PublishRelay<NSDictionary>()
    /// 配置加载动画插件
    let APIProvider: MoyaProvider<MultiTarget> = {
        let configuration = URLSessionConfiguration.default
        configuration.headers = .default
        configuration.timeoutIntervalForRequest = 30
        let session = Moya.Session(configuration: configuration, startRequestsImmediately: false)
        let loading = NetworkLoadingPlugin.init()
        return MoyaProvider<MultiTarget>(session: session, plugins: [loading])
    }()
    func loadData() {
        APIProvider.rx.request(api: LoadingAPI.test2("666"))
            .asObservable()
            .subscribe { [weak self] (event) in
                if let dict = event.element as? NSDictionary {
                    self?.data.accept(dict)
                }
            }.disposed(by: disposeBag)
    }
}


🎷 - MVVM使用示例3:


class CacheViewModel: NSObject {
    let disposeBag = DisposeBag()
    struct Input {
        let count: Int
    }
    struct Output {
        let items: Driver<[CacheModel]>
    }
    func transform(input: Input) -> Output {
        let elements = BehaviorRelay<[CacheModel]>(value: [])
        let output = Output(items: elements.asDriver())
        request(input.count)
            .asObservable()
            .bind(to: elements)
            .disposed(by: disposeBag)
        return output
    }
}
extension CacheViewModel {
    func request(_ count: Int) -> Driver<[CacheModel]> {
        CacheAPI.cache(count).request()
            .asObservable()
            .mapHandyJSON(HandyDataModel<[CacheModel]>.self)
            .compactMap { $0.data }
            .observe(on: MainScheduler.instance) // 结果在主线程返回
            .delay(.seconds(1), scheduler: MainScheduler.instance) // 延时1秒返回
            .asDriver(onErrorJustReturn: []) // 错误时刻返回空
    }
}


🎷 - 链式请求使用示例4:


class ChainViewModel: NSObject {
    let disposeBag = DisposeBag()
    let data = PublishRelay<NSDictionary>()
    func chainLoad() {
        requestIP()
            .flatMapLatest(requestData)
            .subscribe(onNext: { [weak self] data in
                self?.data.accept(data)
            }, onError: {
                print("Network Failed: \($0)")
            }).disposed(by: disposeBag)
    }
}
extension ChainViewModel {
    func requestIP() -> Observable<String> {
        return ChainAPI.test.request()
            .asObservable()
            .map { ($0 as! NSDictionary)["origin"] as! String }
            .catchAndReturn("") // 异常抛出
    }
    func requestData(_ ip: String) -> Observable<NSDictionary> {
        return ChainAPI.test2(ip).request()
            .asObservable()
            .map { ($0 as! NSDictionary) }
            .catchAndReturn(["data": "nil"])
    }
}


🎷 - 批量请求使用示例5:


class BatchViewModel: NSObject {
    let disposeBag = DisposeBag()
    let data = PublishRelay<NSDictionary>()
    /// 配置加载动画插件
    let APIProvider: MoyaProvider<MultiTarget> = {
        let configuration = URLSessionConfiguration.default
        configuration.headers = .default
        configuration.timeoutIntervalForRequest = 30
        let session = Moya.Session(configuration: configuration, startRequestsImmediately: false)
        let loading = NetworkLoadingPlugin.init()
        return MoyaProvider<MultiTarget>(session: session, plugins: [loading])
    }()
    func batchLoad() {
        Observable.zip(
            APIProvider.rx.request(api: BatchAPI.test).asObservable(),
            APIProvider.rx.request(api: BatchAPI.test2("666")).asObservable(),
            APIProvider.rx.request(api: BatchAPI.test3).asObservable()
        ).subscribe(onNext: { [weak self] in
            guard var data1 = $0 as? Dictionary<String, Any>,
                  let data2 = $1 as? Dictionary<String, Any>,
                  let data3 = $2 as? Dictionary<String, Any> else {
                      return
                  }
            data1 += data2
            data1 += data3
            self?.data.accept(data1)
        }, onError: {
            print("Network Failed: \($0)")
        }).disposed(by: disposeBag)
    }
}


HandyJSON


该模块是基于HandyJSON封装网络数据解析

大致分为以下3个部分:

HandyDataModel:网络外层数据模型

HandyJSONError:解析错误相关

RxHandyJSON:HandyJSON数据解析,目前提供两种解析方案

方案1 - 结合HandyDataModel模型使用解析出data数据

方案2 - 根据keyPath解析出指定key的数据,前提条件数据源必须字典形式

🎷 - 结合网络部分使用示例:

func request(_ count: Int) -> Driver<[CacheModel]> {
    CacheAPI.cache(count).request()
        .asObservable()
        .mapHandyJSON(HandyDataModel<[CacheModel]>.self)
        .compactMap { $0.data }
        .observe(on: MainScheduler.instance) // 结果在主线程返回
        .delay(.seconds(1), scheduler: MainScheduler.instance) // 延时1秒返回
        .asDriver(onErrorJustReturn: []) // 错误时刻返回空
}


CocoaPods Install


Ex: 导入网络架构API
- pod 'RxNetworks/MoyaNetwork'
Ex: 导入数据解析
- pod 'RxNetworks/HandyJSON'
Ex: 导入加载动画插件
- pod 'RxNetworks/MoyaPlugins/Loading'


最后


搞OC的小伙伴们也可以使用我的另一款网络插件KJNetworkPlugin

再分享一个MVVM + RxSwift + CTMediatror + MJRefresh + DZNEmptyDataSet 组件化思路的基础架构,喜欢就去用吧别犹豫。

再附上一个开发加速库KJCategoriesDemo地址 🎷喜欢的老板们可以点个星🌟


Demo


大体流程差不多就是这样,Demo也写的很详细,大家可以自己去看看🎷

RxNetworksDemo

提示:如果觉得有帮助,请帮忙点个星 ⭐..

谢谢.🎇

后序有相关插件,也会慢慢补充..

相关文章
|
25天前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch 中的动态计算图:实现灵活的神经网络架构
【8月更文第27天】PyTorch 是一款流行的深度学习框架,它以其灵活性和易用性而闻名。与 TensorFlow 等其他框架相比,PyTorch 最大的特点之一是支持动态计算图。这意味着开发者可以在运行时定义网络结构,这为构建复杂的模型提供了极大的便利。本文将深入探讨 PyTorch 中动态计算图的工作原理,并通过一些示例代码展示如何利用这一特性来构建灵活的神经网络架构。
50 1
|
6天前
|
存储 监控 物联网
蜂窝网络基础架构详解:从基站到核心网
蜂窝网络基础架构详解:从基站到核心网
28 9
|
12天前
|
编解码 人工智能 文件存储
卷积神经网络架构:EfficientNet结构的特点
EfficientNet是一种高效的卷积神经网络架构,它通过系统化的方法来提升模型的性能和效率。
18 1
|
20天前
|
JSON 监控 编译器
|
21天前
|
网络协议 安全 网络性能优化
OSI 模型详解:网络通信的七层架构
【8月更文挑战第31天】
107 0
|
21天前
|
前端开发 开发者 C#
WPF开发者必读:MVVM模式实战,轻松实现现代桌面应用架构,让你的代码更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,MVVM(Model-View-ViewModel)模式通过分离应用程序的逻辑和界面,提高了代码的可维护性和可扩展性。本文介绍了MVVM模式的三个核心组件:Model(数据模型)、View(用户界面)和ViewModel(处理数据绑定和逻辑),并通过示例代码展示了如何在WPF项目中实现MVVM模式。通过这种方式,开发者可以构建更加高效和可扩展的桌面应用程序。
44 0
|
1月前
|
Java Android开发 Kotlin
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
24 0
|
1月前
|
Java Android开发 开发者
Android项目架构设计问题之使用Retrofit2作为网络库如何解决
Android项目架构设计问题之使用Retrofit2作为网络库如何解决
30 0
|
23天前
|
Kubernetes Cloud Native Docker
云原生之旅:从容器到微服务的架构演变
【8月更文挑战第29天】在数字化时代的浪潮下,云原生技术以其灵活性、可扩展性和弹性管理成为企业数字化转型的关键。本文将通过浅显易懂的语言和生动的比喻,带领读者了解云原生的基本概念,探索容器化技术的奥秘,并深入微服务架构的世界。我们将一起见证代码如何转化为现实中的服务,实现快速迭代和高效部署。无论你是初学者还是有经验的开发者,这篇文章都会为你打开一扇通往云原生世界的大门。
|
8天前
|
运维 Cloud Native Devops
云原生架构的崛起与实践云原生架构是一种通过容器化、微服务和DevOps等技术手段,帮助应用系统实现敏捷部署、弹性扩展和高效运维的技术理念。本文将探讨云原生的概念、核心技术以及其在企业中的应用实践,揭示云原生如何成为现代软件开发和运营的主流方式。##
云原生架构是现代IT领域的一场革命,它依托于容器化、微服务和DevOps等核心技术,旨在解决传统架构在应对复杂业务需求时的不足。通过采用云原生方法,企业可以实现敏捷部署、弹性扩展和高效运维,从而大幅提升开发效率和系统可靠性。本文详细阐述了云原生的核心概念、主要技术和实际应用案例,并探讨了企业在实施云原生过程中的挑战与解决方案。无论是正在转型的传统企业,还是寻求创新的互联网企业,云原生都提供了一条实现高效能、高灵活性和高可靠性的技术路径。 ##
18 3