解耦-用RAC处理网络请求

最近接手的项目中使用了RAC,也研究学习了下,发现使用RAC确实清晰便利了许多,下面记录一下用RAC处理网络请求实现解耦

首先看一下项目层次,除了MVC之外,每个小模块都有一个Manager层来管理所有的网络请求,当然,如果你的项目是MVVM的话,可以直接放到ViewModel层里面.

比如说我们有一个"我"这个模块,里面有一个TableView,是我的朋友的列表,对应朋友信息Model,然后我们在进入这个页面的时候请求一次服务器,拿到所有朋友信息.
在请求的时候,我们一般会调用自己二次封装AFHTTPSessionManager的AFN请求管理类,里面有我们的一些基本配置之类的,然后拼接URL,加上参数就调用了.

但是这里面有一个问题,当你的项目越来越大,你请求的URL会遍布整个项目,每个Controller中都会有好几个URL,好几个参数,当这些东西在后面维护中要变化的时候,维护起来就乱了很多.
所以我们给每个模块都设置一个网络管理层,是NetworkManager也好,是ViewModel也好,都是这个作用.

下面看两种请求的例子:

#import <Foundation/Foundation.h>
#import <ReactiveObjC/ReactiveObjC.h>
#import "NetworkTool.h"
#import "FriendModel.h"

@interface MeNetworkManager : NSObject

/// 获取所有朋友列表
+ (RACSignal *)getAllFriends;

/// 添加朋友
+ (RACSignal *)addFriendWithPersonID:(NSInteger)personID;

@end

#import "MeNetworkManager.h"

@implementation MeNetworkManager

/// 获取所有朋友列表
+ (RACSignal *)getAllFriends {
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [[NetworkTool sharedInstance] requestWithPath:@"url" requestType:@"get" requestParamter:nil responseObjctClass:[FriendModel class] completionBlock:^(BOOL isSuccess, id object, NSError *error) {
            if (isSuccess) {
                [subscriber sendNext:object];
                [subscriber sendCompleted];
            } else {
                [subscriber sendError:error];
            }
        }];
        return nil;
    }];
}

/// 添加朋友
+ (RACSignal *)addFriendWithPersonID:(NSInteger)personID {
    NSMutableDictionary *paramter = [NSMutableDictionary dictionary];
    [paramter setObject:@(personID) forKey:@"personID"];
    
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        [[NetworkTool sharedInstance] requestWithPath:@"url" requestType:@"post" requestParamter:paramter responseObjctClass:nil completionBlock:^(BOOL isSuccess, id object, NSError *error) {
            if (isSuccess) {
                [subscriber sendNext:nil];
                [subscriber sendCompleted];
            } else {
                [subscriber sendError:error];
            }
        }];
        return nil;
    }];
}


@end

其中,NetworkTool是二次封装AFN网络请求类,其中方法每个人都有不同写法.总之最后把请求成功接收到的数据转Model后把对象sendNext出去就好;如果没有数据返回,就判断是否成功,然后sendNext个nil就好
在Controller里面,我们引用这个模块的网络管理者,然后调用即可

#import "MeViewController.h"
#import "MeNetworkManager.h"

@interface MeViewController ()<UITableViewDataSource,UITableViewDelegate>

@property (nonatomic, strong) UITableView *friendsTableView;  /**< 朋友列表 */
@property (nonatomic, strong) NSArray *friends;               /**< 数据源 */

@end

@implementation MeViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //加载动画 loading...
    [self getData];
}

- (void)getData {
    @weakify(self)
    [[MeNetworkManager getAllFriends] subscribeNext:^(id  _Nullable x) {
        @strongify(self)
        //加载动画loading...消失
        //拿到数据,更新数据源,刷新tableView(可调用MJRefresh等...)
        FriendModel *friendModel = (FriendModel *)x;
        if (friendModel.friends.count > 0) {
            self.friends = friendModel.friends;
            [self.friendsTableView reloadData];
        }
    } error:^(NSError * _Nullable error) {
        //失败处理
    }];
}

@end

多了一层的好处是每层的职责单一,相互直接依赖降低了(就是解耦),容易拓展功能和后期的维护,如果更改了接口的话,可以直接去NetworkManager中更改,不用再去Controller中全局搜索更改了,更加清晰,达到集中管理请求的目的;
而且当业务需求增加了,其他Controller也需要调用这个接口的时候,可以直接引用这个NetworkManager调用请求方法,不用再复制粘贴一遍了

推荐阅读更多精彩内容

  • 大红袍,为王者香。 很少见这么霸气外露的茶,远远的自楚河汉界的那边一路攻城掠地而来,逼得我无处可逃。 品一脉岩骨花...
    行度竹林风阅读 43评论 0 0
  • 我是一个特别注重仪式感的人。 比如在过年的时候就是要说吉利的话说新年快乐。比如在父母亲节的时候就一定要...
    阿双啊阅读 111评论 0 0
  • 我离开一些地方 何尝不是这些地方离开我 毕竟离开后会想念的是我 而不是那些地方
    旒苏阅读 103评论 0 5
  • 这个夏天,出于一名秦皇岛本地土著的自觉,一定要去海边开启暴走模式,打卡、集齐小岛的各个海滩。 虽然已经立秋,但是小...
    夜兔神乐酱阅读 123评论 0 1