前言
Subject是一個代理,它既是Observer,也是Observable。因為它是一個Observer,它可以訂閱一個或多個Observable;因為它是一個Observable,它又可以被其他的Observer訂閱。它可以傳遞/轉發作為Observer收到的值,也可以主動發射值。
Subject在RxSwift中的實現有四種:
PublishSubjectReplaySubjectBehaviorSubjectVariable
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不具備的。
