博客> 简单对比 YTKNetwork 和 STNetTaskQueue
简单对比 YTKNetwork 和 STNetTaskQueue
2017-12-14 10:55 评论:0 阅读:1387 kevin0571
ios 网络 YTKNetwork STNetTaskQueue

简单对比 YTKNetwork 和 STNetTaskQueue

先放出两个项目的GitHub地址:
YTKNetwork: https://github.com/yuantiku/YTKNetwork 由唐巧大神及其猿题库团队开发。
STNetTaskQueue: https://github.com/kevin0571/STNetTaskQueue

STNetTaskQueue 是我在做一个Side Project 的时候写的管理网络请求的库,目前被使用在多个线上的项目。其设计的基本思想和 YTKNetwork 类似,引用 YTKNetwork 介绍里的原话:

YTKNetwork 的基本的思想是把每一个网络请求封装成对象。所以使用 YTKNetwork,你的每一个请求都需要继承YTKRequest类,通过覆盖父类的一些方法来构造指定的网络请求。

把每一个网络请求封装成对象其实是使用了设计模式中的 Command 模式,它有以下好处:

将网络请求与具体的第三方库依赖隔离,方便以后更换底层的网络库。实际上 YTKNetwork 最初是基于 ASIHttpRequest 的,我们只花了两天,就很轻松地切换到了 AFNetworking。
方便在基类中处理公共逻辑,例如猿题库的数据版本号信息就统一在基类中处理。
方便在基类中处理缓存逻辑,以及其它一些公共逻辑。
方便做对象的持久化。
当然,如果说它有什么不好,那就是如果你的工程非常简单,这么写会显得没有直接用 AFNetworking 将请求逻辑写在 Controller 中方便,所以 YTKNetwork 并不合适特别简单的项目

类似的,每一个网络请求都需要继承 STNetTask。但是在 STNetTaskQueue 里做了另外一层抽象,就是 STNetTaskQueueHandler,由handler来决定请求应该怎么被处理。也就是说,理论上 STNetTaskQueue 能被实现于 HTTP 之外的协议。STNetTaskQueueHandler 的 HTTP 实现默认包含在库里,也就是 STHTTPNetTaskQueueHandler。在很早之前 STHTTPNetTaskQueueHandler 只是对 AFNetworking 的一层封装,后来改为直接用 NSURLSession 实现了。

接下来对比一下用 YTKNetwork 和 STNetTaskQueue 的一些特性:

YTKNetWork STNetTaskQueue
缓存 YES NO
文件断点续传 YES NO
block回调 YES YES
Delegate回调 YES YES
批量请求 YES YES
自动打包请求参数 NO YES
扩展到其它协议 NO YES
关于“自动打包请求参数”

在 AFNetworking 和 YTKNetwork 里,一般都会使用 NSDictionary 来返回请求参数,如:

NSDictionary *params = @{
    @"post_id": postId,
    @"title": title
};

这里引入了一个问题:如果title为nil,会导致程序crash。需要对title进行nil check才能安全的执行打包请求参数的逻辑,当参数很多的时候代码将会很累赘。

而在 STHTTPNetTask 里:

@interface STTestPostNetTask : STHTTPNetTask

@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *body;
@property (nonatomic, strong) NSDate *date;
@property (nonatomic, assign) int userId;
@property (nonatomic, strong) NSString<STIgnore> *ignored; // This property is ignored when packing the request.
@property (nonatomic, strong, readonly) NSDictionary *post;

@end

以上是一个简单的 STHTTPNetTask 子类,当我们需要发送这个请求的时候:

STTestPostNetTask *testPostTask = [STTestPostNetTask new];
testPostTask.title = title;
testPostTask.body = body;
testPostTask.userId = 1;
testPostTask.date = [NSDate new];
testPostTask.ignored = @"test";
[[STNetTaskQueue sharedQueue] addTaskDelegate:self uri:testPostTask.uri];
[[STNetTaskQueue sharedQueue] addTask:testPostTask];

如果 title 或者 body 为 nil,在自动打包请求参数的时候将会被忽略。也就是说大部分情况下,开发者将不需要直接构造 NSDictionary,STHTTPNetTaskQueueHandler 将帮你处理请求参数的打包。默认情况下,STHTTPNetTaskQueueHandler 会参照这样的命名规范:

userId -> user_id

这样就可以保持在Objc里保持该有的命名风格了。当然如果你想支持其它的命名转换规则,可以通过覆盖 STHTTPNetTaskRequestObjectDefaultSeparator 或者 parameterNameSeparator 来返回不同的分隔符。

关于“扩展到其它协议”

大部分情况下,STHTTPNetTaskQueueHandler 已经够用了,但是在某些情况下应用可能在某些场景下需要使用长链接,而且希望在UI层调用网络请求的时候能保持一致的风格,那么就需要实现自定义的 STNetTaskQueueHandler 了。比如在之前有个项目,后台设计所有的接口都是可通过长链接或短链接来请求的,由客户端根据自己的需求来决定。基于这个场景,自定义 STNetTaskQueueHandler 的实现大致是这样的:

// 已知已定义 SocketNetTask 是使用长链接发送请求时使用的 NetTask
@implementation MyNetTaskQueueHandler
{
    STHTTPNetTaskQueueHandler *_httpHandler; // 如果请求的是 HTTP 请求,则直接通过 httpHandler 来处理
}

// 省略了一些初始化

- (void)netTaskQueue:(STNetTaskQueue *)netTaskQueue handleTask:(STNetTask *)task
{
    if ([task ifKindOfClass:[STHTTPNetTask class]]) {
        [_httpHandler netTaskQueue:netTaskQueue handleTask:task];
    }
    else if ([task isKindOfClass[SocketNetTask class]]) {
        // 处理你的长链接请求,比如使用 CocoaAsyncSocket 来处理。
    }
    else {
        NSAssert(NO, @"Invalid net task");
    }
}

@end

这样在发送请求的使用就可以使用统一的风格了:

AHTTPNetTask *aHTTPNetTask = [AHTTPNetTask new]; // 一个HTTP的请求,继承自 STHTTPNetTask
[[STNetTaskQueue sharedQueue] addTask:aHttpNetTask];

ASocketNetTask *aSocketNetTask = [ASocketNetTask new]; // 一个长链接请求,继承自 SocketNetTask
[[STNetTaskQueue sharedQueue] addTask:aSocketNetTask];

// 回调也使用统一的风格

总结

使用 YTKNetwork 和 STNetTaskQueue 各有各的好处,YTKNetwork 经过了更多的线上项目的验证,STNetTaskQueue 才刚刚开始,类似缓存的功能如果在后续要求的人多了,会陆续加上。
如果你有自动打包请求参数,或者扩展的其它协议的需求,STNetTaskQueue 可能是更好的选择。

P.S. 如果对 YTKNetwork 的描述有任何错误,欢迎提出。欢迎大家谈论和对 STNetTaskQueue 提出建议。

收藏
0
sina weixin mail 回到顶部