Subjects
創(chuàng)建 Observable
序列之后, 要預(yù)先將要發(fā)出的數(shù)據(jù)準(zhǔn)備好, 等到有人訂閱時(shí), 再將數(shù)據(jù)通過 Event
發(fā)出去.
我們希望 Observable
序列能在運(yùn)行時(shí)動(dòng)態(tài)的 獲得
或者說 產(chǎn)生
一個(gè)新數(shù)據(jù), 再通過 Event
發(fā)送出去. 比如: 訂閱一個(gè)輸入框的輸入內(nèi)容, 當(dāng)用戶每輸入一個(gè)字后, 這個(gè)輸入框關(guān)聯(lián)的 Observable
就會(huì)發(fā)出一個(gè)帶有輸入內(nèi)容的 Event
, 通知給所有的訂閱者. 這個(gè)就可以使用 Subjects
來實(shí)現(xiàn).
Subjects 基本介紹
(1) Subjects
它是訂閱者, 也是 Obervable
:
- 它是訂閱者, 因?yàn)樗軌騽?dòng)態(tài)的接收新的值
- 它是一個(gè)
Observable
, 是因?yàn)楫?dāng)Subjects
有了新的值之后, 就會(huì)通過Event
將新值發(fā)出給他的所有訂閱者.
(2) 一共有四種 Subjects
, 分別是 PublishSubject
、BehaviorSubject
邪驮、ReplaySubject
坠陈、 Variable(已廢棄)
和 BehaviorRelay(Variable替代品)
.
- 它們都是
Observable
, 它們的訂閱者都能收到它們發(fā)出的Event
- 直到
Subject
發(fā)出.complete
或者.error
的Event
之后, 該Subject
才會(huì)終結(jié), 不再發(fā)出.next
事件. - 對(duì)于那些在
Subject
終結(jié)后再訂閱的訂閱者, 也能收到一條.complete
或者.error
的Event
, 告訴這個(gè)新訂閱者, 該Subject
已經(jīng)終結(jié) - 它們的區(qū)別在于 : 當(dāng)一個(gè)新的訂閱者剛訂閱它的時(shí)候,能不能收到
Subject
以前發(fā)出的舊Event
, 如果能,又可以收到多少個(gè)Event
.
(3) Subject 的常用方法
- onNext() :
on(.next):
的簡寫, 該方法相當(dāng)于subject
接收到一個(gè).next
事件. - onError() :
on(.error):
的簡寫, 該方法相當(dāng)于subject
接收到一個(gè).error
事件. - onCompleted() :
on(.completed):
的簡寫, 該方法相當(dāng)于subjet
接收到一個(gè).completed
事件
PublishSubject
(1) 基本介紹
-
PublishSubject
是最普通的Subjet
, 它不需要初始值就能創(chuàng)建. -
PublishSubject
的訂閱者從開始訂閱的時(shí)間點(diǎn)起,可以收到訂閱Subject
發(fā)出的新的Event
, 而不會(huì)收到他們?cè)谟嗛喦耙寻l(fā)出的Event
.
PublishSubject.png
(2)案例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
//創(chuàng)建一個(gè)PublishSubject
let subject = PublishSubject<String>()
subject.onNext("11") //此時(shí)沒有訂閱者,不會(huì)輸出
//首次訂閱
subject.subscribe(onNext: { str in
print("第一次訂閱: ", str)
}, onCompleted: {
print("第一次訂閱 : onCompleted")
}).disposed(by: disposeBag)
//有訂閱者,會(huì)輸出
subject.onNext("22")
subject.subscribe(onNext: { (str) in
print("第二次訂閱: ", str)
}, onCompleted: {
print("第二次訂閱 : onCompleted")
}).disposed(by: disposeBag)
subject.onNext("33")//兩個(gè)訂閱者,輸出兩遍
subject.onCompleted()//結(jié)束兩個(gè)訂閱者,打印兩遍
subject.onNext("44")//再次發(fā)送event,不會(huì)打印
//再有新的訂閱者,會(huì)收到onCompleted消息,通知新的訂閱者,該Subject已經(jīng)終結(jié)
subject.subscribe(onNext: { (str) in
print("第三次訂閱: ", str)
}, onCompleted: {
print("第三次訂閱 : onCompleted")
}).disposed(by: disposeBag)
}
//輸出結(jié)果
第一次訂閱: 22
第一次訂閱: 33
第二次訂閱: 33
第一次訂閱 : onCompleted
第二次訂閱 : onCompleted
第三次訂閱 : onCompleted
BehaviorSubject
(1) 基本介紹
-
BehaviorSubject
需要通過一個(gè)默認(rèn)初始值來創(chuàng)建 - 當(dāng)一個(gè)訂閱者來訂閱它的時(shí)候, 這個(gè)訂閱者會(huì)立即收到
BehaviorSubject
上一個(gè)發(fā)出的event
, 之后就是正常流程
BehaviorSubject.png
(2) 使用示例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "111")
//第一次訂閱subject(先發(fā)出上一個(gè)event)
subject.subscribe { (event) in
print("第一次訂閱: ", event)
}.disposed(by: disposeBag)
//發(fā)送next事件
subject.onNext("222")
subject.onError(NSError(domain: "local", code: 0, userInfo: nil))
//重復(fù)結(jié)束event,輸出error
subject.subscribe { (event) in
print("第二次訂閱: ",event)
}.disposed(by: disposeBag)
}
//輸出結(jié)果
第一次訂閱: next(111)
第一次訂閱: next(222)
第一次訂閱: error(Error Domain=local Code=0 "(null)")
第二次訂閱: error(Error Domain=local Code=0 "(null)")
ReplaySubject
(1) 基本介紹
-
ReplaySubject
在創(chuàng)建的時(shí)候需要設(shè)置一個(gè)bufferSize
, 表示它發(fā)送過的event
緩存?zhèn)€數(shù). 比如 : 一個(gè)ReplaySubject
的bufferSize
設(shè)置為2
, 它發(fā)出了三個(gè).next
的event
, 那么這個(gè)subscriber
就會(huì)立即收到前面緩存的兩個(gè).next
的event
(2) 時(shí)序圖
-
ReplaySubject
的bufferSize
為2
- 下面兩條訂閱, 訂閱時(shí)間點(diǎn)不同.
ReplaySubject
的訂閱者一開始就能受到ReplaySubject
之前發(fā)出的兩個(gè)Event
(如果有的話).
ReplaySubject.png
(3)案例
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 2);
//連續(xù)發(fā)出三個(gè)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)
}
//輸出結(jié)果
第一次訂閱 next(2)
第一次訂閱 next(3)
第一次訂閱 next(4)
第二次訂閱 next(3)
第二次訂閱 next(4)
第一次訂閱 completed
第二次訂閱 completed
第三次訂閱 next(3)
第三次訂閱 next(4)
第三次訂閱 completed
BehaviorRelay
(1) 基本介紹
-
BehaviorRelay
是作為Variable
的替代者出現(xiàn)的. 它的本質(zhì)其實(shí)也是對(duì)BehaviorRelay
的封裝, 所以它也必須要通過一個(gè)默認(rèn)的初始值進(jìn)行創(chuàng)建 -
BehaviorReplay
具有BehaviorSubject
的功能, 能夠向它的訂閱者發(fā)出上一個(gè)event
以及之后新創(chuàng)建的event
- 與
BehaviorSubject
不同的是滥酥,不需要也不能手動(dòng)給BehaviorReply
發(fā)送completed
或者error
事件來結(jié)束它(BehaviorRelay
會(huì)在銷毀時(shí)自動(dòng)發(fā)送.complete
的 event)石景。 -
BehaviorReplay
有一個(gè)value
屬性, 我們通過這個(gè)屬性可以獲取最新值. 而通過它的accept()
方法可以對(duì)值進(jìn)行修改.
(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")
}
//輸出結(jié)果
第一次訂閱: next(222)
第一次訂閱: next(333)
第二次訂閱 : next(333)
第一次訂閱: next(444)
第二次訂閱 : next(444)