一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情。
- 本文主要介绍下
RxAlamofire,Rx关于网络请求的封装
1. Swift中网络框架概述
我们在swift开发中,通常会对网络请求进行封装,通常会使用Alamofire(相当于我们OC中的AFNetWork)或者Moya/Moya,它是对我们Alamofire的封装,使用Moya上的一张图来表达下他们的关系
关于这些框架的使用,网上都有,大家基本上都是封装下,这里就不说明了。主要介绍下使用RxSwift把我们的网络请求封装城序列。
2. 使用RxSwift封装原生请求
我们使用RxSwift对原生的请求封装,我们使用demo例子查看使用。
response
let url = URL(string: "http://www.douban.com/j/app/radio/channels")!
URLSession.shared.rx.response(request: URLRequest(url: url))
.subscribe(onNext: { (response,data) in
print("response:\(response) \n data:\(data)" )
}, onError: { (error) in
print("error:\(error)")
}, onCompleted: {
print("网络请求完成")
}) {
print("销毁咯")
}.disposed(by: self.disposeBag)
请求结果
看下实现,主要是对原生的URL request进行封装,处理返回的数据,错误信息,积极状态。
data
URLSession.shared.rx.data(request: URLRequest(url: self.url))
.subscribe(onNext: { (data) in
print("data:\(data)" )
}, onError: { (error) in
print("error:\(error)")
}, onCompleted: {
print("网络请求完成")
}) {
print("销毁咯")
}.disposed(by: self.disposeBag)
请求结果
看下实现,可以发现是对Response的封装,将请求结果进行map转换为我们Data类型。
json
继续看下json的封装
URLSession.shared.rx.json(request: URLRequest(url: self.url))
.subscribe(onNext: { (json) in
print(json)
}, onError: { (error) in
print("error:\(error)")
}, onCompleted: {
print("网络请求完成")
}) {
print("销毁咯")
}.disposed(by: self.disposeBag)
打印结果
看下实现
把我们请求的数据进行转换为json数据。可以发现它们的关系是json -> data -> response.我们在使用的过程使用response即可。
3. RxAlamofire的使用
当然我们实际使用过程一般都是使用三方封装好的框架,很少使用原始的网络请求,我们需要做一些统一的处理。我们看下RxAlamofire的使用吧。
RxAlamofire.requestJSON(.get, url)
.debug()
.subscribe(onNext: { (r, json) in
if let dict = json as? [String: AnyObject] {
// let valDict = dict["rates"] as! Dictionary<String, AnyObject>
// print(dict)
print(">>>>>>>>>>>>>>>>>>>自己的打印>>>>>>>>>>>>>>>>>>>>>>")
print(dict)
}
}, onError: { (error) in
})
.disposed(by: disposeBag)
我们同样请求上面的链接,get请求,打印结果:
可以发现对于请求,封装了打印的信息。继续看下实现
底层是对我们Alamofire进行DataRequest
- 简单的使用
{
let stringURL = ""
// MARK: With Alamofire engine
_ = json(.get, stringURL)
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
_ = request(.get, stringURL)
.flatMap { request in
request.validate(statusCode: 200..<300)
.validate(contentType: ["text/json"])
.rx.json()
}
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// progress
_ = request(.get, stringURL)
.flatMap {
$0
.validate(statusCode: 200..<300)
.validate(contentType: ["text/json"])
.rx.progress()
}
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// just fire upload and display progress
if let urlRequest = try? urlRequest(.get, stringURL) {
_ = upload(Data(), urlRequest: urlRequest)
.flatMap {
$0
.validate(statusCode: 200..<300)
.validate(contentType: ["text/json"])
.rx.progress()
}
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
}
// progress and final result
// uploading files with progress showing is processing intensive operation anyway, so
// this doesn't add much overhead
_ = request(.get, stringURL)
.flatMap { request -> Observable<(Data?, RxProgress)> in
let validatedRequest = request
.validate(statusCode: 200..<300)
.validate(contentType: ["text/json"])
let dataPart = validatedRequest
.rx.data()
.map { d -> Data? in d }
.startWith(nil as Data?)
let progressPart = validatedRequest.rx.progress()
return Observable.combineLatest(dataPart, progressPart) { ($0, $1) }
}
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// MARK: Alamofire manager
// same methods with any alamofire manager
let manager = Session.default
// simple case
_ = manager.rx.json(.get, stringURL)
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// NSURLHTTPResponse + JSON
_ = manager.rx.responseJSON(.get, stringURL)
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// NSURLHTTPResponse + String
_ = manager.rx.responseString(.get, stringURL)
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// NSURLHTTPResponse + Validation + String
_ = manager.rx.request(.get, stringURL)
.flatMap {
$0
.validate(statusCode: 200..<300)
.validate(contentType: ["text/json"])
.rx.string()
}
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// NSURLHTTPResponse + Validation + NSURLHTTPResponse + String
_ = manager.rx.request(.get, stringURL)
.flatMap {
$0
.validate(statusCode: 200..<300)
.validate(contentType: ["text/json"])
.rx.responseString()
}
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// NSURLHTTPResponse + Validation + NSURLHTTPResponse + String + Progress
_ = manager.rx.request(.get, stringURL)
.flatMap { request -> Observable<(String?, RxProgress)> in
let validatedRequest = request
.validate(statusCode: 200..<300)
.validate(contentType: ["text/something"])
let stringPart = validatedRequest
.rx.string()
.map { d -> String? in d }
.startWith(nil as String?)
let progressPart = validatedRequest.rx.progress()
return Observable.combineLatest(stringPart, progressPart) { ($0, $1) }
}
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
}
这里列举了一些简单的使用
4. 总结
对于RxSwift在网络中的应用,就是把我们网络的请求转换为可观察序列,通过发送它的请求结果和状态,做到链式响应。