zwvista

导航

ReactiveX 学习笔记(37)RxSwift 的 share 和 RxCocoa 的 Driver

冷数据流,热数据流

Hot and Cold Observables

  • 冷数据流不能共享数据,热数据流能共享数据
  • 冷数据流需要有订阅者才能发布数据,热数据流无需订阅者即可发布数据

publish, connect, refCount, replay

Understanding Connectable Observable Sequences in RxSwift

  • 普通数据流调用 publish 操作符后变为可连接数据流。
  • 可连接数据流调用 connect 操作符后变为热数据流。热数据流可以在所有订阅者中共享所发布的数据。
  • 可连接数据流调用 refCount 操作符后具有引用计数功能,订阅数从0到1时自动连接变为热数据流,从1到0时自动断开连接重新变回可连接数据流。
  • 可连接数据流或热数据流调用 replay 操作符后具有缓存功能,能缓存一部分或全部所发布的数据,新的订阅者在订阅时能够接收到订阅之前缓冲区的数据。

Publish
RefCount
Replay

share, replay, share(replay:scope:)

RxSwift: share vs replay vs shareReplay
Understanding the RxSwift share operator
RxSwift: share()-ing is Caring

  • share 相当于 publish + refCount,有引用计数功能,订阅数从0到1时自动连接,从1到0时自动断开连接。
  • replay 没有引用计数功能,需要调用 connect 之后才能连接。
  • replay 有缓存功能,可以指定缓存的大小。
  • share(replay:scope:) 相当于 share + replay,同时具有引用计数功能和缓存功能。
    scope = .whileConnected 只有在连接时才缓存数据,断开连接时缓存被释放,重新连接后新的订阅者不会接收到订阅之前发布的数据。
    scope = .forever 即使断开连接时缓存仍然保持,重新连接后新的订阅者会接收到订阅之前发布的数据。

Driver

Driver 是 RxCocoa 中的一个 Trait,即具有某些特性的数据流。
Driver 数据流的特性

  • 不会出错
  • 在主线程观察数据
  • 共享副作用 share(replay: 1, scope: .whileConnected)

示例

Driver

let results = query.rx.text
    .throttle(.milliseconds(300), scheduler: MainScheduler.instance)
    .flatMapLatest { query in
        fetchAutoCompleteItems(query)
            .observeOn(MainScheduler.instance)  // results are returned on MainScheduler
            .catchErrorJustReturn([])           // in the worst case, errors are handled
    }
    .share(replay: 1)                           // HTTP requests are shared and results replayed
                                                // to all UI elements

results
    .map { "\($0.count)" }
    .bind(to: resultCount.rx.text)
    .disposed(by: disposeBag)

results
    .bind(to: resultsTableView.rx.items(cellIdentifier: "Cell")) { (_, result, cell) in
        cell.textLabel?.text = "\(result)"
    }
    .disposed(by: disposeBag)

这段代码的功能为发出 http 请求,将结果数据与两个控件绑定

  • .observeOn(MainScheduler.instance)
    在主线程中监听数据,
  • .catchErrorJustReturn([])
    出错时返回空数组
  • .share(replay: 1)
    结果数据需要与两个控件绑定,必须使用热数据流来共享数据。如果使用冷数据流来绑定两个控件将导致发送两次 http 请求
let results = query.rx.text.asDriver()        // This converts a normal sequence into a `Driver` sequence.
    .throttle(.milliseconds(300), scheduler: MainScheduler.instance)
    .flatMapLatest { query in
        fetchAutoCompleteItems(query)
            .asDriver(onErrorJustReturn: [])  // Builder just needs info about what to return in case of error.
    }

results
    .map { "\($0.count)" }
    .drive(resultCount.rx.text)               // If there is a `drive` method available instead of `bind(to:)`,
    .disposed(by: disposeBag)              // that means that the compiler has proven that all properties
                                              // are satisfied.
results
    .drive(resultsTableView.rx.items(cellIdentifier: "Cell")) { (_, result, cell) in
        cell.textLabel?.text = "\(result)"
    }
    .disposed(by: disposeBag)

这段代码改用 Driver 来完成同样的功能。

  • .asDriver()
    将数据流转换为 Driver 数据流,后者是一种共享数据流,具有共享数据的功能
  • .asDriver(onErrorJustReturn: [])
    出错时返回空数组,Driver 数据流能在主线程中监听数据,
  • .drive(resultCount.rx.text)
    Driver 必须使用 drive 方法来绑定控件

Signal

Signal 是 RxCocoa 中的一个 Trait,即具有某些特性的数据流。
Signal 数据流的特性

  • 不会出错
  • 在主线程观察数据
  • 共享计算资源 share(scope: .whileConnected)
  • 没有缓存,新的订阅者不会接收订阅之前所发布的数据

posted on 2022-08-20 14:37  zwvista  阅读(336)  评论(0编辑  收藏  举报