RXSwift中Driver的使用

默认情况,我们使用Observable来监听时,有以下几个问题.
先来看个例子:

  • 模拟请求接口查询数据
// 模拟查询数据
    func dealwithData(inputText:String)-> Observable<Any>{
        print("请求网络了 \(Thread.current)") // data
        return Observable<Any>.create({ (ob) -> Disposable in
            if inputText == "1234" {
                ob.onError(NSError.init(domain: "com.lgcooci.cn", code: 10086, userInfo: nil))
            }

            DispatchQueue.global().async {
                print("发送之前看看: \(Thread.current)")
                ob.onNext("已经输入:\(inputText)")
                ob.onCompleted()
            }
            return Disposables.create()
        })
    }
  • 使用ob序列监听
let result = inputTF.rx.text.skip(1).flatMap { [weak self](input) -> Observable<Any> in
     return (self?.dealwithData(inputText: input ?? ""))!
}
  • 接下来我们连续订阅两次
//第一次订阅
result.subscribe { (even) in
    print(even)
    print(Thread.current)
}.disposed(by: disposeBag)
//第二次订阅
result.subscribe { (even) in
    print(even)
    print(Thread.current)
}.disposed(by: disposeBag)

提前准备好的界面如下:


  • 运行 ,输入框输入1 打印结果如下


打印结果中看出, 订阅两次时,我们会请求两次网络.
请求多次网络解决办法
添加观察时增加共享指定:

let result = inputTF.rx.text.skip(1).flatMap { [weak self](input) -> Observable<Any> in
    return (self?.dealwithData(inputText: input ?? ""))!
}.share(replay: 1, scope: .whileConnected)

再运行:



看到订阅两次但是只执行一次监听方法.但是我们仍然看到接受到事件时是处于子线程, 意味着不能更新UI事件.继续解决

响应异步解决办法 : 指定序列监听执行线程

let result = inputTF.rx.text.skip(1).flatMap { [weak self](input) -> Observable<Any> in
     return (self?.dealwithData(inputText: input ?? ""))!
            .observeOn(MainScheduler.instance)
}.share(replay: 1, scope: .whileConnected)

打印结果:


我们看到当输入内容为1234时,我们调用了
ob.onError(NSError.init(domain: "com.lgcooci.cn", code: 10086, userInfo: nil))
可是输入1234时并没有监听到onError事件.

增加错误handle

let result = inputTF.rx.text.skip(1).flatMap { [weak self](input) -> Observable<Any> in
     return (self?.dealwithData(inputText: input ?? ""))!
     .observeOn(MainScheduler.instance)
     .catchErrorJustReturn("检测到了错误事件")
}.share(replay: 1, scope: .whileConnected)

然后我们再输入1234


总结:

我们为了处理 请求多次网络解决办法,响应异步解决办法 , 增加错误handle , 需要分别额外增加三步处理, 可是在实际项目中,往往不会使用这种方式. 而是用Driver来处理.

Driver(特征序列)

1 - 基本介绍

(1)Driver 可以说是最复杂的 trait,它的目标是提供一种简便的方式在 UI 层编写响应式代码。
(2)如果我们的序列满足如下特征,就可以使用它:

  • 不会产生 error 事件
  • 一定在主线程监听(MainScheduler)
  • 共享状态变化(shareReplayLatestWhileConnected)
2 - 为什么要使用 Driver?

(1)Driver 最常使用的场景应该就是需要用序列来驱动应用程序的情况了,比如:

通过 CoreData 模型驱动 UI

使用一个 UI 元素值(绑定)来驱动另一个 UI 元素值

(2)与普通的操作系统驱动程序一样,如果出现序列错误,应用程序将停止响应用户输入。
(3)在主线程上观察到这些元素也是极其重要的,因为 UI 元素和应用程序逻辑通常不是线程安全的。
(4)此外,使用构建 Driver 的可观察的序列,它是共享状态变化。

3 - 使用案例
let result = inputTF.rx.text.orEmpty
            .asDriver()
            .flatMap {  return self.dealwithData(inputText: $0)
            .asDriver(onErrorJustReturn: "检测到了错误事件") }

第一次订阅

//第一次订阅,并把内容绑定到另一个UILabel上
result.map{ "长度:\( ($0 as! String).count )" }
.drive(self.textLabel.rx.text)
.disposed(by: disposeBag)

第二次订阅

//第二次订阅,并把内容绑定到另一个UIButton上
result.map { "\($0 as! String)"}
.drive(self.btn.rx.title())
.disposed(by: disposeBag)

执行结果:


总结:

Driver特征是序列实际在开发中专门用于

  • 不会产生 error 事件
  • 一定在主线程监听(MainScheduler)
  • 共享状态变化(shareReplayLatestWhileConnected)

由于 drive 方法只能被 Driver 调用。这意味着,如果代码存在 drive,那么这个序列不会产生错误事件并且一定在主线程监听。这样我们就可以安全的绑定 UI元素。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。