RxSwift学习-23-RxAlamofire的使用

1,900 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情

  • 本文主要介绍下RxAlamofire,Rx关于网络请求的封装

1. Swift中网络框架概述

我们在swift开发中,通常会对网络请求进行封装,通常会使用Alamofire(相当于我们OC中的AFNetWork)或者Moya/Moya,它是对我们Alamofire的封装,使用Moya上的一张图来表达下他们的关系

image.png

关于这些框架的使用,网上都有,大家基本上都是封装下,这里就不说明了。主要介绍下使用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)

请求结果

image.png

看下实现,主要是对原生的URL request进行封装,处理返回的数据,错误信息,积极状态。

image.png

  • 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)

请求结果 image.png

看下实现,可以发现是对Response的封装,将请求结果进行map转换为我们Data类型。

image.png

  • 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)

打印结果

image.png

看下实现

image.png

把我们请求的数据进行转换为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请求,打印结果:

image.png

可以发现对于请求,封装了打印的信息。继续看下实现

image.png

底层是对我们Alamofire进行DataRequest

image.png

  • 简单的使用
{

    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在网络中的应用,就是把我们网络的请求转换为可观察序列,通过发送它的请求结果和状态,做到链式响应