前言
Subject
是一個代理,它既是Observer
,也是Observable
。因為它是一個Observer
,它可以訂閱一個或多個Observable
;因為它是一個Observable
,它又可以被其他的Observer
訂閱。它可以傳遞/轉發作為Observer
收到的值,也可以主動發射值。
Subject
在RxSwift
中的實現有四種:
PublishSubject
ReplaySubject
BehaviorSubject
Variable
PublishSubject
代理
我們先以PublishSubject
為例來解釋Subject
是一個代理的含義。
let subject = PublishSubject<Int>()
subject.subscribe({ (event) in
print("Event:\(event)")
})
subject.onNext(1)
subject.onNext(2)
subject.onCompleted()
Subject
作為一個Observable
提供了subscribe
等方法。在訂閱之后,我們調用了onNext()
,向Observer
發射了1
、2
,以及onCompleted()
。打印結果和我們預期的是一樣的。
Event:next(1)
Event:next(2)
Event:completed
我們可以調用Subject
的on
系列方法主動給Observer
發送值。
Subject
可以作為代理轉發訂閱到的結果。例如:
let subject = PublishSubject<Int>()
subject.subscribe({ (event) in
print("Event:\(event)")
})
let reveseSubject = Observable<Int>.create({ (observer) -> Disposable in
observer.onNext(1)
observer.onNext(2)
observer.onCompleted()
return Disposables.create()
})
reveseSubject.subscribe(subject)
subject
訂閱了reveseSubject
,並將結果轉發給了Observer
。
注意:
Observer
訂閱subject
時不會收到訂閱之前subject
的值。
let subject = PublishSubject<Int>()
subject.onNext(0)
subject.subscribe({ (event) in
print("Event:\(event)")
})
subject.onNext(1)
subject.onNext(2)
subject.onCompleted()
上述代碼結果為:
Event:next(1)
Event:next(2)
Event:completed
observer
無法接收到0
這個值。
ReplaySubject
ReplaySubject
和PublishSubject
不同的是,Observer
有可能接收到訂閱之前的值。
let subject = ReplaySubject<Int>.create(bufferSize: 1)
subject.onNext(0)
subject.subscribe({ (event) in
print("Event:\(event)")
})
subject.onNext(1)
subject.onNext(2)
subject.onCompleted()
上述代碼結果為:
Event:next(0)
Event:next(1)
Event:next(2)
Event:completed
ReplaySubject
具有重放(replay)的功能,replay的個數可以通過參數指定。我們可以將其理解為緩存的效果。
一般我們使用ReplaySubject
的時候,都是先發射,后訂閱,然后通過指定緩存的大小,可以獲取對應的值。(注意:不考慮Error和Completed)。
let subject = ReplaySubject<Int>.create(bufferSize: 1)
subject.onNext(0)
subject.onNext(1)
subject.onNext(2)
subject.onCompleted()
subject.subscribe({ (event) in
print("Event:\(event)")
})
上述代碼,我們指定了bufferSize
等於1,所以只緩存了最新的值,打印結果:
Event:next(2)
Event:completed
當我們需要緩存所有值的時候,可以調用createUnbounded()
方法。
ReplaySubject
.create(bufferSize: 0) 等同於 PublishSubject ()。
BehaviorSubject
BehaviorSubject
類似於ReplaySubject
具有緩存能力,但是略有不同。
- 只緩存一個最新值,類似
ReplaySubject.create(bufferSize: 1)
- 需要提供默認值
let behaviorSubject = BehaviorSubject<Int>(value: 1)
behaviorSubject.subscribe({ (event) in
print("Event:\(event)")
})
打印結果為:
Event:next(1)
使用BehaviorSubject
有一點好處,我們可以確定當Observer
訂閱時,至少可以收到最新的一個值。
Variable
Variable
和BehaviorSubject
又很相似,Variable
是BehaviorSubject
的一個封裝,同樣具備了緩存最新值和提供默認值的能力。但是Variable
沒有on
系列方法,只提供了value
屬性。
直接對value
進行set
等同於調用了onNext()
方法。
這表明了Variable
不會發射error
也不會發射completed
在Variable
被銷毀的時候會調用發射completed
給Observer
在訂閱Variable
的時候,我們無法直接調用subscribe
方法,需要先調用asObservable()
方法。
let variable = Variable<Int>(1)
variable.asObservable().subscribe({ (event) in
print("Event:\(event)")
})
variable.value = 2
上述結果為:
Event:next(1)
Event:next(2)
Event:completed
Variable
可以用來儲存數據,因為我們可以擁有value
的get
和set
方法。比如:
let variable = Variable(1)
print("Value: \(variable.value)")
variable.value = 2
print("Value: \(variable.value)")
打印結果為:
Value: 1
Value: 2
這是BehaviorSubject
不具備的。