浅谈网络层设计(XXHNetwork封装缓存、日志输出、参数,返回数据拦截控制等)

  • 对于网络层的设计,相信大家都不会陌生,最知名当属于AFNetworking。但是我们实际开发过程中网络层的任务不仅仅需要单纯的网络请求,而是需要处理关于请求数据相关的整个一大块,例如:数据缓存、日志、code校对、错误分析等等。我们希望网络层能起到后台与实际业务的桥梁作用,同时网络层不可以染指业务逻辑。考虑低耦合要求,我们往往会把网络层设计成一个独立模块。而我们大名顶顶的AFNetworking并不能实现这一多功能要求,那么我们就需要对AFNetworking二次封装增加新的功能以满足我们所需要的网络层要求。

一、如何设计(个人浅谈)

  • 1.封装形式:对AFNetworking封装分为两种形式,block(集约型)和代理(离散型)。所以我们需要对这两种进行选择。
  • 2.缓存模块:业务有时候需要一些重要对数据能够缓存下来而不是每次请求网络。所以我们需要一个缓存数据的模块。
  • 3.日志系统:对于每次请求我们不可能说每次都能一次性搞定,而是需要跟后台不断调试,包括我们自己调试,这样我们就需要一个日志模块,这个模块能够打印出关于请求的所有信息,成功能够打印出正确数据,失败能够打印具体的失败信息等,我们只需要简单看看日志就能发现问题所在而不是通过LLDB打断点一步一步调试找出错误。
  • 4.低偶合性。网络层必须是一个独立的模块,不能够跟业务逻辑纠缠在一起。对于网络层来讲,我只给你业务提供数据,至于你要用数据去干什么,我并不关心。另一方面,网络层必须跟AFNetworking低耦合,一旦哪天我们不想要用AFNetworking可以轻松替换。
  • 5:可操控性:很多时候会出现这种情况,我们给的请求参数明显不对,或者后台返回的数据明显不是业务需求数据。如果我们不加以处理,那么就会导致请求错误,并且这个错误数据流入地业务端,业务端首先需要去甄别数据的好坏,其次再加以使用。一旦业务的请求接口过多势必会导致业务层压力增大。对此,我们需要将这些不必要的错误扼杀在网络层, 所以一些时候网络层需要对请求的参数,以及返回的数据进行校对,或者修订。这样可以减少业务层的压力负担,使其能更好的关注业务逻辑。
  • 6.简单,易懂的代码:有些简单的请求如果进行一系列分析的话有会导致代码看上去很烦乱,所以我们还需要提供一些简单易懂的调用方法。
  • 7.请求控制:一些没有必要的请求我们需要及时去除。例如:切换页面后,请求还在进行,这时候请求已经没有必要了,我们需要停止,防止流量的浪费,同时对于一些麻烦的请求(大数据的上传下载等)还可以提升流畅度。

二、模式缺陷

1.block形式的缺陷

  • block不够安全,稍微不注意就形成循环引用,导致对象释放不了。这种循环引用,一旦出现就比较难检查出来。
  • block很难追踪,难以维护
  • block会延长相关对象的生命周期
  • 在多通信时候,block显得不够直观也不易维护
  • block效率低,block出栈需要将使用的数据从栈内存拷贝到堆内存

2.block形式的优点

  • 使用更简单,易维护,能够直接访问上下文,获取数据方便
  • 省去了写代理的很多代码

3.delegate形式的优点

  • delegate更安全, delegate 的方法是分离开的,不会引用上下文,不容易循环引用
  • 代码的连贯性不是很好,没有 block 好读
  • delegate 让多个方法分成一组,只需要设置一次,就可以多次回调。即同一个请求可能会多次调用的时候delegate只需要设置一次,而block需要多次,这种情况下也推荐用delegate形式
  • delegate运行成本低,delegate只是保存了一个对象指针,直接回调,没有额外消耗

3.delegate形式的缺点

  • 使用繁琐,请求接口数量多的时候delegate要写更多的代码。
  • 方法的声明和实现分离开来,代码的连贯性不是很好。
  • 需要临时存储很多数据,跟业务交接不方便

三、个人方案

1.业务分析

  • 开始公司业务量不多的时候,接口较少,也比较简单。自己用的都是block形式,轻型、简单、代码易读易修改。这样一方面符合刚开始的快速迭代,二方面也节省时间。但是随着后来业务量的增加,业务功能的细致化后发现,自己的业务层开始变的非常臃肿,对于一些接口,业务还需要去自己检测数据的格式符不符合要求。一些相同的请求,多次不同地方调用,block就的在多个地方多次重写等等导致业务层再次变的繁琐...

2.问题处理 - XXHNetwork

  • 对于相同接口多次调用等问题我们应该使用delegate模式,但由于之前使用大量的block一时间全部更换不现实,而且一些简单的接口更换后反而显得臃肿,所以最终采用但是混合模式,即网络层最外层即提供block形式接口,同时也提供delegate形式接口,至于需要用哪种形式,可由开发人员根据业务需求自行选择,以达到最优效果。

四、XXHNetwork封装缓存、日志输出、参数,返回数据拦截控制

1.数据缓存

XXHNetwork提供了独立的缓存模块(XHNetworkCacheManager)该模块底层运用的是YYCache,因为YYCache LRU算法比较符合我们现实的使用场景,当然我们系统提供的NSCache也是ok的,看个人喜好吧。缓存模块提供下面功能

  • 支持最大缓存数量
  • 缓存版本控制、app版本检测
  • 根据请求shouldAllIgnoreCache判断是否需要缓存
  • 缓存的有效时长
  • 内存、磁盘两中存储方式
  • 缓存数据增、删、改、查

2.日志输出

日志输出由独立的模块XHNetworkLogManager控制,里面提供各种情况(成功、失败)下日志输出接口,只需要调用初始化方法传入相应数据即可!

  • func appendURL:用于打印请求head、body信息
  • func logDebugInfo:用于打印请求返回数据信息
    当然你也可以根据自己的需求在这个模块增加日志收集接口等等个人业务相关等需求

3.底层接口分离

  • XXHNetwork跟底层AF交互的只有XHApiProxy一个类,同时只有一个方法(func callNetwork)这一个方法跟AF交互,其他所有不同方式请求处理都是通过调用该方法,也就是以后如果想替换AFNetworking那么只需要更换这一个方法即可替换非常方便!
  • 底层方法callNetwork还增加了一些基本的code处理,对于一些明显的错误,例如token失效等,这里直接放在最底层进行处理这样只需要处理一次即可。
  • XHApiProxy提供供外界调用基本请求接口,同时还提供了请求控制接口,可以实现部分或者全部取消请求。

4.上层接口

  • block形式:XHNetworkBlockManager,只要实现相应的成功、失败回调即可,相关的错误类型查看XHNetworkErrorType
  • delegate形式:XHNetworkDelegateManager,这个可用于参数控制,数据返回检测,只要实现相应的代理即可实现相应功能,详细看注释。
  • XHNetworkConfigution:网络配置,网络基本配置在这里修改
  • XHNetworkRequestConfig:请求配置,你可以根据业务需求初始化具体的配置,你也可以不用管使用默认的请求配置。
  • XHURLResponse:返回数据对象,不管成功还是失败都会返回该对象,该对象包含了所有需要信息,AN返回的基本数据responseObject为(content),error:为错误信息。其他信息请查看注释。

5.使用

  • block使用:
XHNetworkBlockManager.shared.request(Method: XHNetworkRequestType.get, APIString: "", Parameters: params, SuccessBlock: { (successResponse) in
            print("--------------方式一(block形式)请求数据成功----------")
            self.testManager.loadData()
        }) { (failureResponse) in
            print("--------------方式一请求数据失败----------")
        }
  • delegate使用:
    1.创建一个继承XHNetworkDelegateManager的业务请求中间管理类:XHNetworkTestManager。这个类专门来实现一些公用的业务代理XHAPIManagerValidator、XHAPIManager等当然你也可以不用,那么你的代理实现就必须在具体的业务中,这样会增加业务代码量,所以不推荐。
    2.调用
    统一加载方法: loadData
    加载更多方法:loadMoreData
//代理方式调用
self.testManager.loadData()

3.在具体业务中创建一个中间管理类的对象testManager
然后在业务接着完成剩余代理的实现

lazy var testManager:XHNetworkTestManager = {
        
        let testManager = XHNetworkTestManager()
        testManager.callBackDelagate = self
        testManager.paramSourceDelegate = self
        return testManager
    }()
//参数代理,在这里传送请求参数
    func configeApiParams(Manager manager: XHNetworkDelegateManager) -> [String : Any]? {
        
        let dic = [String : Any]()
        return dic
    }
    //返回数据代理
    func requesApiSuccess(Manager manager: XHNetworkDelegateManager) {
        print("--------------方式二(delegate形式)请求数据成功----------")
    }
    
    func requesApiFailure(Manager manager: XHNetworkDelegateManager) {
        print("--------------方式二请求数据失败----------")
    }

源码地址请点击这里,欢迎大神指导,若考虑不周的地方,请大家多提意见!如果喜欢或者对您有帮助,希望能给个小星星,多谢!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • iOS网络架构讨论梳理整理中。。。 其实如果没有APIManager这一层是没法使用delegate的,毕竟多个单...
    yhtang阅读 5,174评论 1 23
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,093评论 1 32
  • 原文地址:http://casatwy.com/iosying-yong-jia-gou-tan-wang-luo...
    大澎湃阅读 1,502评论 1 2
  • 已是蒸蒸灼日高,蝉鸣悲苦柳枝梢。思风化雨把凉调。 又念瑶池桃子结,更怀南国荔红邀。蒲葵轻起漫相摇
    喻芷楚阅读 284评论 2 3
  • 一天很短 短得来不及拥抱清晨 就已经手握黄昏, 转眼之间,生日以过, 都说儿女的生日是母亲的难日, 感谢母亲给予我...
    阿卉_8120阅读 250评论 0 0