可被监听的序列也是观察者

AsyncSubject

image.png

AsyncSubject 将在源 Observable 产生完成事件后,发出最后一个元素(仅仅只有最后一个元素),如果源 Observable 没有发出任何元素,只有一个完成事件。那 AsyncSubject 也只有一个完成事件。

image.png

它会对随后的观察者发出最终元素。如果源 Observable 因为产生了一个 error 事件而中止, AsyncSubject 就不会发出任何元素,而是将这个 error 事件发送出来。

演示:

let disposeBag = DisposeBag()
let subject = AsyncSubject()

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("")
subject.onNext("")
subject.onNext("")
subject.onCompleted()

输出:

Subscription: 1 Event: next()
Subscription: 1 Event: completed

PublishSubject

image.png

PublishSubject 将对观察者发送订阅后产生的元素,而在订阅前发出的元素将不会发送给观察者。如果你希望观察者接收到所有的元素,你可以通过使用 Observable 的 create 方法来创建 Observable,或者使用 ReplaySubject。

image.png

如果源 Observable 因为产生了一个 error 事件而中止, PublishSubject 就不会发出任何元素,而是将这个 error 事件发送出来。

演示:

let disposeBag = DisposeBag()
let subject = PublishSubject()

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("")
subject.onNext("")

subject
  .subscribe { print("Subscription: 2 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("️")
subject.onNext("️")

结果:

Subscription: 1 Event: next()
Subscription: 1 Event: next()
Subscription: 1 Event: next(️)
Subscription: 2 Event: next(️)
Subscription: 1 Event: next(️)
Subscription: 2 Event: next(️)

ReplaySubject

image.png

ReplaySubject 将对观察者发送全部的元素,无论观察者是何时进行订阅的。

这里存在多个版本的 ReplaySubject,有的只会将最新的 n 个元素发送给观察者,有的只会将限制时间段内最新的元素发送给观察者。

如果把 ReplaySubject 当作观察者来使用,注意不要在多个线程调用 onNext, onError 或 onCompleted。这样会导致无序调用,将造成意想不到的结果。

演示:

let disposeBag = DisposeBag()
let subject = ReplaySubject.create(bufferSize: 1)

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("")
subject.onNext("")

subject
  .subscribe { print("Subscription: 2 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("️")
subject.onNext("️")

结果:

Subscription: 1 Event: next()
Subscription: 1 Event: next()
Subscription: 2 Event: next()
Subscription: 1 Event: next(️)
Subscription: 2 Event: next(️)
Subscription: 1 Event: next(️)
Subscription: 2 Event: next(️)

BehaviorSubject

image.png

当观察者对 BehaviorSubject 进行订阅时,它会将源 Observable 中最新的元素发送出来(如果不存在最新的元素,就发出默认元素)。然后将随后产生的元素发送出来。

image.png

如果源 Observable 因为产生了一个 error 事件而中止, BehaviorSubject 就不会发出任何元素,而是将这个 error 事件发送出来。

演示:

let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "")

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("")
subject.onNext("")

subject
  .subscribe { print("Subscription: 2 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("️")
subject.onNext("️")

subject
  .subscribe { print("Subscription: 3 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("")
subject.onNext("")

结果:

Subscription: 1 Event: next()
Subscription: 1 Event: next()
Subscription: 1 Event: next()
Subscription: 2 Event: next()
Subscription: 1 Event: next(️)
Subscription: 2 Event: next(️)
Subscription: 1 Event: next(️)
Subscription: 2 Event: next(️)
Subscription: 3 Event: next(️)
Subscription: 1 Event: next()
Subscription: 2 Event: next()
Subscription: 3 Event: next()
Subscription: 1 Event: next()
Subscription: 2 Event: next()
Subscription: 3 Event: next()

Variable

通常使用var:

// 在 ViewController 中
var model: Model? = nil {
    didSet { updateUI(with: model) }
}

override func viewDidLoad() {
    super.viewDidLoad()

    model = getModel()
}

func updateUI(with model: Model?) { ... }
func getModel() -> Model { ... }

使用Variable:

// 在 ViewController 中
let model: Variable = Variable(nil)

override func viewDidLoad() {
    super.viewDidLoad()

    model.asObservable()
        .subscribe(onNext: { [weak self] model in
            self?.updateUI(with: model)
        })
        .disposed(by: disposeBag)

    model.value = getModel()
}

func updateUI(with model: Model?) { ... }
func getModel() -> Model { ... }

第一种使用 var 的方式十分常见,在 ViewController 中监听 Model 的变化,然后刷新页面。

第二种使用 Variable 则是 RxSwift 独有的。Variable 几乎提供了 var 的所有功能。另外,加上一条非常重要的特性,就是可以通过调用 asObservable() 方法转换成序列。然后你可以对这个序列应用操作符,来合成其他的序列。所以,如果我们声明的变量需要提供 Rx 支持,那就选用 Variable 这个类型。

Variable 封装了一个 BehaviorSubject,所以它会持有当前值,并且 Variable 会对新的观察者发送当前值。它不会产生 error 事件。Variable 在 deinit 时,会发出一个 completed 事件。

ControlProperty

ControlProperty 专门用于描述 UI 控件属性的,它具有以下特征:

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

你可能感兴趣的:(可被监听的序列也是观察者)