看了前面介绍的创建Observable的方式, 我们应该会想,在项目的实际使用中,大多数情况都是预先不知道序列值的.比如:我们要订阅文本框内容输入的变化.
这个时候,RxSwift为我们提供了Subjects,既是订阅者,也是 Observable.
Subjects分为四种类型: PublishSubject、BehaviorSubject、ReplaySubject、Variable(BehaviorRelay).我们分别来介绍下他们的用法及区别:
1. PublishSubject
- 无需初始值
- 订阅者只能收到他们 订阅后 发出的Event.
let subject = PublishSubject<String>()
subject.onNext("第一条消息")
subject.subscribe(onNext: { string in
print("第1次订阅:", string)
}, onCompleted:{
print("第1次订阅:onCompleted")
}).disposed(by: disposeBag)
subject.onNext("第二条消息")
subject.subscribe(onNext: { string in
print("第2次订阅:", string)
}, onCompleted:{
print("第2次订阅:onCompleted")
}).disposed(by: disposeBag)
subject.onNext("第三条消息")
//让subject结束
subject.onCompleted()
//subject结束后会发出.next事件了。
subject.onNext("第四条消息")
subject.subscribe(onNext: { string in
print("第3次订阅:", string)
}, onCompleted:{
print("第3次订阅:onCompleted")
}).disposed(by: disposeBag)
//第1次订阅: 第二条消息
//第1次订阅: 第三条消息
//第2次订阅: 第三条消息
//第1次订阅:onCompleted
//第2次订阅:onCompleted
//第3次订阅:onCompleted
2. BehaviorSubject
- 需要传入初始值
- 当一个订阅者来订阅它的时候,这个订阅者会立即收到 BehaviorSubjects 上一个及之后 发出的新的 event。
let subject = BehaviorSubject(value: "初始消息")
subject.onNext("第一条消息")
subject.subscribe(onNext: { string in
print("第1次订阅:", string)
}, onCompleted:{
print("第1次订阅:onCompleted")
}).disposed(by: disposeBag)
subject.onNext("第二条消息")
subject.subscribe(onNext: { string in
print("第2次订阅:", string)
}, onCompleted:{
print("第2次订阅:onCompleted")
}).disposed(by: disposeBag)
subject.onNext("第三条消息")
//让subject结束
subject.onCompleted()
//subject完成后会发出.next事件了。
subject.onNext("第四条消息")
subject.subscribe(onNext: { string in
print("第3次订阅:", string)
}, onCompleted:{
print("第3次订阅:onCompleted")
}).disposed(by: disposeBag)
//第1次订阅: 第一条消息
//第1次订阅: 第二条消息
//第2次订阅: 第二条消息
//第1次订阅: 第三条消息
//第2次订阅: 第三条消息
//第1次订阅:onCompleted
//第2次订阅:onCompleted
//第3次订阅:onCompleted
3.ReplaySubject
- 需要一个初始bufferSize(缓存的event的个数)
- 当一个订阅者来订阅它的时候,这个订阅者会立即收到 ReplaySubject 最近两个及之后 发出的新的 event。
例如下面代码, 一个 ReplaySubject 的 bufferSize 设置为 2,它发出了 4 个 .next 的 event("第五条消息"是在结束后.onNext的,不会发出),那么它会将后两个(最近的两个-bufferSize个数)event 给缓存起来。
此时如果有一个 subscriber 订阅了这个 ReplaySubject,那么这个 subscriber 就会立即收到前面缓存的两个.next 的 event。(例如:第三次订阅,收到了前面缓存的最近的两个消息2,3)及之后发出的4消息)
如果一个 subscriber 订阅已经结束的 ReplaySubject,除了会收到缓存的 .next 的 event外,还会收到那个终结的 .error 或者 .complete 的event。(第五次订阅)
//第一次订阅 总共收到了 1,+2,3,4消息
//第二次订阅 总共收到了 1,2,+3,4消息
//第三次订阅 总共收到了 2,3,+4消息
//第四次订阅 总共收到了 3,4+无消息
//第五次订阅 总共收到了 3,4+无消息
let subject = ReplaySubject<String>.create(bufferSize: 2)
subject.onNext("第一条消息")
subject.subscribe(onNext: { string in
print("第1次订阅:", string)
}, onCompleted:{
print("第1次订阅:onCompleted")
}).disposed(by: disposeBag)
subject.onNext("第二条消息")
subject.subscribe(onNext: { string in
print("第2次订阅:", string)
}, onCompleted:{
print("第2次订阅:onCompleted")
}).disposed(by: disposeBag)
subject.onNext("第三条消息")
subject.subscribe(onNext: { string in
print("第3次订阅:", string)
}, onCompleted:{
print("第3次订阅:onCompleted")
}).disposed(by: disposeBag)
subject.onNext("第四条消息")
subject.subscribe(onNext: { string in
print("第4次订阅:", string)
}, onCompleted:{
print("第4次订阅:onCompleted")
}).disposed(by: disposeBag)
//让subject结束
subject.onCompleted()
//subject完成后就不会发出.next事件了。
subject.onNext("第五条消息")
subject.subscribe(onNext: { string in
print("第5次订阅:", string)
}, onCompleted:{
print("第5次订阅:onCompleted")
}).disposed(by: disposeBag)
//第1次订阅: 第一条消息
//第1次订阅: 第二条消息
//第2次订阅: 第一条消息
//第2次订阅: 第二条消息
//第1次订阅: 第三条消息
//第2次订阅: 第三条消息
//第3次订阅: 第二条消息
//第3次订阅: 第三条消息
//第1次订阅: 第四条消息
//第2次订阅: 第四条消息
//第3次订阅: 第四条消息
//第4次订阅: 第三条消息
//第4次订阅: 第四条消息
//第1次订阅:onCompleted
//第2次订阅:onCompleted
//第3次订阅:onCompleted
//第4次订阅:onCompleted
//第5次订阅: 第三条消息
//第5次订阅: 第四条消息
//第5次订阅:onCompleted
4. Variable => BehaviorRelay
- Variable 其实就是对 BehaviorSubject 的封装,所以它也必须要通过一个默认的初始值进行创建。
- Variable 具有 BehaviorSubject 的功能,能够向它的订阅者发出上一个 event 以及之后新创建的 event。
- 不同的是,Variable 还会把当前发出的值保存为自己的状态。同时它会在销毁时自动发送 .complete的 event,不需要也不能手动给 Variables 发送 completed或者 error 事件来结束它。
简单地说就是 Variable 有一个 value 属性,我们改变这个 value 属性的值就相当于调用一般 Subjects 的 onNext() 方法,而这个最新的 onNext() 的值就被保存在 value 属性里了,直到我们再次修改它。
Variable已经被BehaviorRelay取代
let variable = Variable("初始消息")
variable.value = "第一条消息"
//第1次订阅
variable.asObservable().subscribe {
print("第1次订阅:", $0)
}.disposed(by: disposeBag)
variable.value = "第二条消息"
//第2次订阅
variable.asObservable().subscribe {
print("第2次订阅:", $0)
}.disposed(by: disposeBag)
variable.value = "第三条消息"
variable.asObservable().subscribe {
print("第3次订阅:", $0)
}.disposed(by: disposeBag)
//ℹ️ [DEPRECATED] `Variable` is planned for future deprecation. Please consider `BehaviorRelay` as a replacement. Read more at: https://git.io/vNqvx
//第1次订阅: next(第一条消息)
//第1次订阅: next(第二条消息)
//第2次订阅: next(第二条消息)
//第1次订阅: next(第三条消息)
//第2次订阅: next(第三条消息)
//第3次订阅: next(第三条消息)
//第1次订阅: completed
//第2次订阅: completed
//第3次订阅: completed
5. BehaviorRelay
- BehaviorRelay 是作为Variable 的替代者出现的。它的本质其实也是对 BehaviorSubject 的封装,所以它也必须要通过一个默认的初始值进行创建。
- BehaviorRelay 具有 BehaviorSubject的功能,能够向它的订阅者发出上一个 event 以及之后新创建的 event。
- 与 BehaviorSubject 不同的是,不需要也不能手动给 BehaviorReply 发送 completed 或者 error 事件来结束它(BehaviorRelay 会在销毁时也不会自动发送 .complete 的 event)。
BehaviorRelay 有一个 value 属性,我们通过这个属性可以获取最新值。而通过它的 accept() 方法可以对值进行修改
let subject = BehaviorRelay<String>(value: "初始值")
subject.accept("第一条消息")
subject.asObservable().subscribe {
print("第1次订阅:", $0)
}.disposed(by: disposeBag)
subject.accept("第二条消息")
subject.asObservable().subscribe {
print("第2次订阅:", $0)
}.disposed(by: disposeBag)
subject.accept("第三条消息")
https://www.jianshu.com/p/def6965b0475
https://blog.csdn.net/qq_30963589/article/details/112171117
网友评论