Subjects
创建 Observable
序列之后, 要预先将要发出的数据准备好, 等到有人订阅时, 再将数据通过 Event
发出去.
我们希望 Observable
序列能在运行时动态的 获得
或者说 产生
一个新数据, 再通过 Event
发送出去. 比如: 订阅一个输入框的输入内容, 当用户每输入一个字后, 这个输入框关联的 Observable
就会发出一个带有输入内容的 Event
, 通知给所有的订阅者. 这个就可以使用 Subjects
来实现.
Subjects 基本介绍
(1) Subjects
它是订阅者, 也是 Obervable
:
- 它是订阅者, 因为它能够动态的接收新的值
- 它是一个
Observable
, 是因为当Subjects
有了新的值之后, 就会通过Event
将新值发出给他的所有订阅者.
(2) 一共有四种 Subjects
, 分别是 PublishSubject
、BehaviorSubject
、ReplaySubject
、 Variable(已废弃)
和 BehaviorRelay(Variable替代品)
.
- 它们都是
Observable
, 它们的订阅者都能收到它们发出的Event
- 直到
Subject
发出.complete
或者.error
的Event
之后, 该Subject
才会终结, 不再发出.next
事件. - 对于那些在
Subject
终结后再订阅的订阅者, 也能收到一条.complete
或者.error
的Event
, 告诉这个新订阅者, 该Subject
已经终结 - 它们的区别在于 : 当一个新的订阅者刚订阅它的时候,能不能收到
Subject
以前发出的旧Event
, 如果能,又可以收到多少个Event
.
(3) Subject 的常用方法
- onNext() :
on(.next):
的简写, 该方法相当于subject
接收到一个.next
事件. - onError() :
on(.error):
的简写, 该方法相当于subject
接收到一个.error
事件. - onCompleted() :
on(.completed):
的简写, 该方法相当于subjet
接收到一个.completed
事件
PublishSubject
(1) 基本介绍
-
PublishSubject
是最普通的Subjet
, 它不需要初始值就能创建. -
PublishSubject
的订阅者从开始订阅的时间点起,可以收到订阅Subject
发出的新的Event
, 而不会收到他们在订阅前已发出的Event
.
(2)案例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
//创建一个PublishSubject
let subject = PublishSubject<String>()
subject.onNext("11") //此时没有订阅者,不会输出
//首次订阅
subject.subscribe(onNext: { str in
print("第一次订阅: ", str)
}, onCompleted: {
print("第一次订阅 : onCompleted")
}).disposed(by: disposeBag)
//有订阅者,会输出
subject.onNext("22")
subject.subscribe(onNext: { (str) in
print("第二次订阅: ", str)
}, onCompleted: {
print("第二次订阅 : onCompleted")
}).disposed(by: disposeBag)
subject.onNext("33")//两个订阅者,输出两遍
subject.onCompleted()//结束两个订阅者,打印两遍
subject.onNext("44")//再次发送event,不会打印
//再有新的订阅者,会收到onCompleted消息,通知新的订阅者,该Subject已经终结
subject.subscribe(onNext: { (str) in
print("第三次订阅: ", str)
}, onCompleted: {
print("第三次订阅 : onCompleted")
}).disposed(by: disposeBag)
}
//输出结果
第一次订阅: 22
第一次订阅: 33
第二次订阅: 33
第一次订阅 : onCompleted
第二次订阅 : onCompleted
第三次订阅 : onCompleted
BehaviorSubject
(1) 基本介绍
-
BehaviorSubject
需要通过一个默认初始值来创建 - 当一个订阅者来订阅它的时候, 这个订阅者会立即收到
BehaviorSubject
上一个发出的event
, 之后就是正常流程
(2) 使用示例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "111")
//第一次订阅subject(先发出上一个event)
subject.subscribe { (event) in
print("第一次订阅: ", event)
}.disposed(by: disposeBag)
//发送next事件
subject.onNext("222")
subject.onError(NSError(domain: "local", code: 0, userInfo: nil))
//重复结束event,输出error
subject.subscribe { (event) in
print("第二次订阅: ",event)
}.disposed(by: disposeBag)
}
//输出结果
第一次订阅: next(111)
第一次订阅: next(222)
第一次订阅: error(Error Domain=local Code=0 "(null)")
第二次订阅: error(Error Domain=local Code=0 "(null)")
ReplaySubject
(1) 基本介绍
-
ReplaySubject
在创建的时候需要设置一个bufferSize
, 表示它发送过的event
缓存个数. 比如 : 一个ReplaySubject
的bufferSize
设置为2
, 它发出了三个.next
的event
, 那么这个subscriber
就会立即收到前面缓存的两个.next
的event
(2) 时序图
-
ReplaySubject
的bufferSize
为2
- 下面两条订阅, 订阅时间点不同.
ReplaySubject
的订阅者一开始就能受到ReplaySubject
之前发出的两个Event
(如果有的话).
(3)案例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 2);
//连续发出三个event
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
//第一次订阅
subject.subscribe { (event) in
print("第一次订阅", event)
}.disposed(by: disposeBag)
subject.onNext("4")
subject.subscribe { (event) in
print("第二次订阅", event)
}
subject.onCompleted();
subject.subscribe { (event) in
print("第三次订阅", event)
}.disposed(by: disposeBag)
}
//输出结果
第一次订阅 next(2)
第一次订阅 next(3)
第一次订阅 next(4)
第二次订阅 next(3)
第二次订阅 next(4)
第一次订阅 completed
第二次订阅 completed
第三次订阅 next(3)
第三次订阅 next(4)
第三次订阅 completed
BehaviorRelay
(1) 基本介绍
-
BehaviorRelay
是作为Variable
的替代者出现的. 它的本质其实也是对BehaviorRelay
的封装, 所以它也必须要通过一个默认的初始值进行创建 -
BehaviorReplay
具有BehaviorSubject
的功能, 能够向它的订阅者发出上一个event
以及之后新创建的event
- 与
BehaviorSubject
不同的是,不需要也不能手动给BehaviorReply
发送completed
或者error
事件来结束它(BehaviorRelay
会在销毁时自动发送.complete
的 event)。 -
BehaviorReplay
有一个value
属性, 我们通过这个属性可以获取最新值. 而通过它的accept()
方法可以对值进行修改.
(2) 案例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
let subject = BehaviorRelay<String>(value: "111");
// 修改value值
subject.accept("222");
//第一次订阅
subject.subscribe { (event) in
print("第一次订阅: ", event)
}.disposed(by: disposeBag)
//修改value值
subject.accept("333")
subject.subscribe { (event) in
print("第二次订阅 :", event)
}.disposed(by: disposeBag)
subject.accept("444")
}
//输出结果
第一次订阅: next(222)
第一次订阅: next(333)
第二次订阅 : next(333)
第一次订阅: next(444)
第二次订阅 : next(444)