RxSwift之Subject
在 RxsWift 中还有一种非常特殊的序列 Subject - 即公也为受。Subject是一个代理,它既是Observer,也是Observable。
PublishSubject
PublishSubject 只对观察者发送订阅后产生的元素,而在订阅前发出的元素将不会发送给观察者。如果你希望观察者接收到所有的元素,你可以通过使用 Observable 的 create 方法来创建 Observable,或者使用 ReplaySubject。
如果源 Observable 因为产生了一个 error 事件而中止, PublishSubject 就不会发出任何元素,而是将这个 error 事件发送出来。
demo
//1:初始化一个PublishSubject 装着Int类型的序列
let publishSub = PublishSubject()
// 2:发送响应序列
publishSub.onNext(1)
// 3:订阅序列
publishSub.subscribe { print("订阅到了:",$0)}
.disposed(by: disposbag)
// 再次发送响应
publishSub.onNext(2)
publishSub.onNext(3)
输出:
订阅到了: next(2)
订阅到了: next(3)
解析
public final class PublishSubject
: Observable
, SubjectType
, Cancelable
, ObserverType
, SynchronizedUnsubscribeType {
typealias Observers = AnyObserver.s
private var _observers = Observers()
public func on(_ event: Event) {
......
dispatch(self._synchronized_on(event), event)
}
func _synchronized_on(_ event: Event) -> Observers {
self._lock.lock(); defer { self._lock.unlock() }
switch event {
case .next:
if self._isDisposed || self._stopped {
return Observers()
}
return self._observers
case .completed, .error:
if self._stoppedEvent == nil {
self._stoppedEvent = event
self._stopped = true
let observers = self._observers
self._observers.removeAll()
return observers
}
return Observers()
}
}
public override func subscribe(_ observer: O) -> Disposable where O.E == Element {
self._lock.lock()
let subscription = self._synchronized_subscribe(observer)
self._lock.unlock()
return subscription
}
func _synchronized_subscribe(_ observer: O) -> Disposable where O.E == E {
......
let key = self._observers.insert(observer.on)
return SubscriptionDisposable(owner: self, key: key)
}
}
源序列订阅时会把observer.on
通过insert
函数装进袋子里,_observers
就是Bag
。
extension AnyObserver {
typealias s = Bag<(Event) -> Void>
}
发出信号时,遍历袋子中的.on
去响应
func dispatch(_ bag: Bag<(Event) -> Void>, _ event: Event) {
bag._value0?(event)
if bag._onlyFastPath {
return
}
let pairs = bag._pairs
for i in 0 ..< pairs.count {
pairs[i].value(event)
}
if let dictionary = bag._dictionary {
for element in dictionary.values {
element(event)
}
}
}
订阅之前发出的信号,没有装进袋子,也无法作出响应。
BehaviorSubject
当观察者对 BehaviorSubject 进行订阅时,它会将源 Observable 中最新的元素发送出来(如果不存在最新的元素,就发出默认元素)。然后将随后产生的元素发送出来。
如果源 Observable 因为产生了一个 error 事件而中止, BehaviorSubject 就不会发出任何元素,而是将这个 error 事件发送出来。
demo
// 1:创建序列
let behaviorSub = BehaviorSubject.init(value: 100)
// 2:发送信号
behaviorSub.onNext(2)
behaviorSub.onNext(3)
// 3:订阅序列
behaviorSub.subscribe{ print("订阅到了:",$0)}
.disposed(by: disposbag)
// 再次发送
behaviorSub.onNext(4)
behaviorSub.onNext(5)
// 再次订阅
behaviorSub.subscribe{ print("订阅到了:",$0)}
.disposed(by: disposbag)
输出:
订阅到了: next(3)
订阅到了: next(4)
订阅到了: next(5)
订阅到了: next(5)
解析
public final class BehaviorSubject
: Observable
, SubjectType
, ObserverType
, SynchronizedUnsubscribeType
, Cancelable {
public init(value: Element) {
self._element = value
}
public func on(_ event: Event) {
。。。。。。
dispatch(self._synchronized_on(event), event)
}
func _synchronized_on(_ event: Event) -> Observers {
self._lock.lock(); defer { self._lock.unlock() }
if self._stoppedEvent != nil || self._isDisposed {
return Observers()
}
switch event {
case .next(let element):
self._element = element
case .error, .completed:
self._stoppedEvent = event
}
return self._observers
}
public override func subscribe(_ observer: O) -> Disposable where O.E == Element {
self._lock.lock()
let subscription = self._synchronized_subscribe(observer)
self._lock.unlock()
return subscription
}
func _synchronized_subscribe(_ observer: O) -> Disposable where O.E == E {
。。。。。。
let key = self._observers.insert(observer.on)
observer.on(.next(self._element))
return SubscriptionDisposable(owner: self, key: key)
}
}
订阅时除了把observer.on
装进袋子外,还直接用.next
发送了默认元素_element
。发出信号时,先更新默认元素self._element = element
,然后再同步发出信号。
ReplaySubject
ReplaySubject 将对观察者发送全部的元素,无论观察者是何时进行订阅的。
这里存在多个版本的 ReplaySubject,有的只会将最新的 n 个元素发送给观察者,有的只会将限制时间段内最新的元素发送给观察者。
如果把 ReplaySubject 当作观察者来使用,注意不要在多个线程调用 onNext, onError 或 onCompleted。这样会导致无序调用,将造成意想不到的结果。
demo
ReplaySubject 有两种构建可以指定bufferSize
,也可以不做限制createUnbounded
。
// 1:创建序列
let replaySub = ReplaySubject.create(bufferSize: 2)
// let replaySub = ReplaySubject.createUnbounded()
// 2:发送信号
replaySub.onNext(1)
replaySub.onNext(2)
replaySub.onNext(3)
replaySub.onNext(4)
// 3:订阅序列
replaySub.subscribe{ print("订阅到了:",$0)}
.disposed(by: disposbag)
// 再次发送
replaySub.onNext(7)
replaySub.onNext(8)
replaySub.onNext(9)
输出:
订阅到了: next(3)
订阅到了: next(4)
订阅到了: next(7)
订阅到了: next(8)
订阅到了: next(9)
解析
public class ReplaySubject
: Observable
, SubjectType
, ObserverType
, Disposable {
typealias Observers = AnyObserver.s
typealias DisposeKey = Observers.KeyType
fileprivate var _observers = Observers()
public static func create(bufferSize: Int) -> ReplaySubject {
if bufferSize == 1 {
return ReplayOne()
} else {
return ReplayMany(bufferSize: bufferSize)
}
}
public static func createUnbounded() -> ReplaySubject {
return ReplayAll()
}
}
ReplaySubject
只是个外部类,会根据不通的构建方式去分流给基类(子类)ReplayBufferBase
(ReplayOne
、ReplayMany
和ReplayAll
)。
ReplayBufferBase
private class ReplayBufferBase
: ReplaySubject
, SynchronizedUnsubscribeType {
override func on(_ event: Event) {
。。。。。。
dispatch(self._synchronized_on(event), event)
}
func _synchronized_on(_ event: Event) -> Observers {
self._lock.lock(); defer { self._lock.unlock() }
if self._isDisposed {
return Observers()
}
if self._isStopped {
return Observers()
}
switch event {
case .next(let element):
self.addValueToBuffer(element)
self.trim()
return self._observers
case .error, .completed:
self._stoppedEvent = event
self.trim()
let observers = self._observers
self._observers.removeAll()
return observers
}
}
override func subscribe(_ observer: O) -> Disposable where O.E == Element {
self._lock.lock()
let subscription = self._synchronized_subscribe(observer)
self._lock.unlock()
return subscription
}
func _synchronized_subscribe(_ observer: O) -> Disposable where O.E == E {
if self._isDisposed {
observer.on(.error(RxError.disposed(object: self)))
return Disposables.create()
}
let anyObserver = observer.asObserver()
self.replayBuffer(anyObserver)
if let stoppedEvent = self._stoppedEvent {
observer.on(stoppedEvent)
return Disposables.create()
}
else {
let key = self._observers.insert(observer.on)
return SubscriptionDisposable(owner: self, key: key)
}
}
}
基类ReplayBufferBase
的实现中在订阅装袋前会让各子类处理自己的replayBuffer
函数,其实就是遍历发送Queue
里面的元素(Queue 是个自定义的 Sequence,FIFO队列)。在on
中就是把所有需要.next
类型的元素通过各子类的addValueToBuffer
进行入队操作,同时用trim
做删减更新。
订阅者仍然是由Bag
管理,元素则由Queue
管理。元素的数量是bufferSize
指定的,如果是 1 的话,用个属性赋值就够了,多个才需要Queue
。
ReplayOne
访问_value
来操作元素。
fileprivate final class ReplayOne : ReplayBufferBase {
private var _value: Element?
override func addValueToBuffer(_ value: Element) {
self._value = value
}
override func replayBuffer(_ observer: O) where O.E == Element {
if let value = self._value {
observer.on(.next(value))
}
}
}
ReplayMany
ReplayMany
和ReplayAll
都是ReplayManyBase
的子类。
private class ReplayManyBase: ReplayBufferBase {
fileprivate var _queue: Queue
init(queueSize: Int) {
self._queue = Queue(capacity: queueSize + 1)
}
override func addValueToBuffer(_ value: Element) {
self._queue.enqueue(value)
}
override func replayBuffer(_ observer: O) where O.E == Element {
for item in self._queue {
observer.on(.next(item))
}
}
}
fileprivate final class ReplayMany : ReplayManyBase {
private let _bufferSize: Int
init(bufferSize: Int) {
self._bufferSize = bufferSize
super.init(queueSize: bufferSize)
}
override func trim() {
while self._queue.count > self._bufferSize {
_ = self._queue.dequeue()
}
}
}
ReplayAll
fileprivate final class ReplayAll : ReplayManyBase {
init() {
super.init(queueSize: 0)
}
override func trim() {
}
}
AsyncSubject
AsyncSubject 将在源 Observable 产生完成事件后,发出最后一个元素(仅仅只有最后一个元素),如果源 Observable 没有发出任何元素,只有一个完成事件。那 AsyncSubject 也只有一个完成事件。
它会对随后的观察者发出最终元素。如果源 Observable 因为产生了一个 error 事件而中止, AsyncSubject 就不会发出任何元素,而是将这个 error 事件发送出来。
demo
// 1:创建序列
let asynSub = AsyncSubject.init()
// 2:发送信号
asynSub.onNext(1)
asynSub.onNext(2)
// 3:订阅序列
asynSub.subscribe{ print("订阅到了:",$0)}
.disposed(by: disposbag)
// 再次发送
asynSub.onNext(3)
asynSub.onNext(4)
asynSub.onError(NSError.init(domain: "❌", code: 120, userInfo: "急救中心"))
asynSub.onCompleted()
输出:
订阅到了: error(Error Domain=❌ Code=120 "急救中心")
解析
public final class AsyncSubject
: Observable
, SubjectType
, ObserverType
, SynchronizedUnsubscribeType {
typealias Observers = AnyObserver.s
private var _lastElement: Element?
public func on(_ event: Event) {
#if DEBUG
self._synchronizationTracker.register(synchronizationErrorMessage: .default)
defer { self._synchronizationTracker.unregister() }
#endif
let (observers, event) = self._synchronized_on(event)
switch event {
case .next:
dispatch(observers, event)
dispatch(observers, .completed)
case .completed:
dispatch(observers, event)
case .error:
dispatch(observers, event)
}
}
func _synchronized_on(_ event: Event) -> (Observers, Event) {
self._lock.lock(); defer { self._lock.unlock() }
if self._isStopped {
return (Observers(), .completed)
}
switch event {
case .next(let element):
self._lastElement = element
return (Observers(), .completed)
case .error:
self._stoppedEvent = event
let observers = self._observers
self._observers.removeAll()
return (observers, event)
case .completed:
let observers = self._observers
self._observers.removeAll()
if let lastElement = self._lastElement {
self._stoppedEvent = .next(lastElement)
return (observers, .next(lastElement))
} else {
self._stoppedEvent = event
return (observers, .completed)
}
}
}
public override func subscribe(_ observer: O) -> Disposable where O.E == Element {
self._lock.lock(); defer { self._lock.unlock() }
return self._synchronized_subscribe(observer)
}
func _synchronized_subscribe(_ observer: O) -> Disposable where O.E == E {
if let stoppedEvent = self._stoppedEvent {
......
}
let key = self._observers.insert(observer.on)
return SubscriptionDisposable(owner: self, key: key)
}
}
AsyncSubject
订阅时仍然是装袋管理,但响应的时候,_synchronized_on
函数中,如果是.next
就只更新最后一个元素:self._lastElement = element
,并返回一个空袋子:return (Observers(), .completed)
。只对.completed
和.error
才返回订阅时的袋子容器self._observers
。所以,onnext 的时候没有任何反应,error 和 completed 才会有响应。并且是最后一个元素。