在我们所遇到的事物中,有一部分非常特别。它们既是可监听序列(Observable
)也是观察者(Observer
)。
相同点:一次发送,处处订阅,区别如下表
类型 | 描述 |
---|---|
PublishSubject | 订阅以后产生的所有元素 |
BehaviorSubject | 订阅时会将最新的元素发出来 |
ReplaySubject | 保存最新的n个元素 |
AsyncSubject | 只订阅最后一个和完成事件 或 错误事件 |
-
PublishSubject
PublishSubject
将对观察者发送订阅后产生的元素,而在订阅前发出的元素将不会发送给观察者。
let publishSub = PublishSubject<Int>()
publishSub.onNext(1)
publishSub.subscribe {print("订阅1:\($0)")}
.disposed(by: self.disposeBag)
publishSub.onNext(2)
publishSub.onNext(3)
publishSub.subscribe {print("订阅2:\($0)")}
.disposed(by: self.disposeBag)
publishSub.onNext(4)
publishSub.onNext(5)
输出:
订阅1:next(2)
订阅1:next(3)
订阅1:next(4)
订阅2:next(4)
订阅1:next(5)
订阅2:next(5)
-
BehaviorSubject
当观察者对 BehaviorSubject
进行订阅时,它会将源 Observable 中最新的元素发送出来(如果不存在最新的元素,就发出默认元素)
let behaciorSub = BehaviorSubject(value: 1)
behaciorSub.onNext(2)
behaciorSub.onNext(3)
behaciorSub.subscribe {print("订阅1:\($0)")}
.disposed(by: self.disposeBag)
behaciorSub.onNext(4)
behaciorSub.onNext(5)
behaciorSub.subscribe {print("订阅2:\($0)")}
.disposed(by: self.disposeBag)
behaciorSub.onNext(6)
输出:
订阅1:next(3)
订阅1:next(4)
订阅1:next(5)
订阅2:next(5)
订阅1:next(6)
订阅2:next(6)
-
ReplaySubject
ReplaySubject
将最新的 n 个元素发送给观察者
let replaySub = ReplaySubject<Int>.create(bufferSize: 2)
replaySub.onNext(1)
replaySub.onNext(2)
replaySub.onNext(3)
replaySub.subscribe {print("订阅1:\($0)")}
.disposed(by: self.disposeBag)
replaySub.onNext(4)
replaySub.onNext(5)
replaySub.subscribe {print("订阅2:\($0)")}
.disposed(by: self.disposeBag)
replaySub.onNext(6)
输出:
订阅1:next(2)
订阅1:next(3)
订阅1:next(4)
订阅1:next(5)
订阅2:next(4)
订阅2:next(5)
订阅1:next(6)
订阅2:next(6)
-
AsyncSubject
AsyncSubject
将在源 Observable
产生完成事件后,发出最后一个元素(仅仅只有最后一个元素),如果源 Observable
没有发出任何元素,只有一个完成事件。那 AsyncSubject
也只有一个完成事件。如果发出错误事件,只有一个错误事件。
let asynSub = AsyncSubject<Int>.init()
asynSub.onNext(1)
asynSub.onNext(2)
asynSub.onNext(3)
asynSub.subscribe {print("订阅1:\($0)")}
.disposed(by: self.disposeBag)
asynSub.onNext(4)
asynSub.onNext(5)
asynSub.subscribe {print("订阅2:\($0)")}
.disposed(by: self.disposeBag)
asynSub.onNext(6)
// asynSub.onError(NSError.init(domain: "error", code: 10086, userInfo: nil))
asynSub.onCompleted()
输出:
输出:
订阅1:next(6)
订阅2:next(6)
订阅1:completed
订阅2:completed
or
订阅1:error(Error Domain=error Code=10086 "(null)")
订阅2:error(Error Domain=error Code=10086 "(null)")
分析一个PublishSubject
,其他的就是在初始化时有一点区别。
let publishSub = PublishSubject<Int>()
publishSub.onNext(1)
publishSub.subscribe {print("订阅1:\($0)")}
.disposed(by: self.disposeBag)
publishSub.onNext(2)
(一)、首先来看PublishSubject
的初始化:
public final class PublishSubject<Element>
: Observable<Element>
, SubjectType
, Cancelable
, ObserverType
, SynchronizedUnsubscribeType {
public typealias SubjectObserverType = PublishSubject<Element>
/// Creates a subject.
public override init() {
super.init()
#if TRACE_RESOURCES
_ = Resources.incrementTotal()
#endif
}
public func on(_ event: Event<Element>) {
#if DEBUG
self._synchronizationTracker.register(synchronizationErrorMessage: .default)
defer { self._synchronizationTracker.unregister() }
#endif
dispatch(self._synchronized_on(event), event)
}
点进PublishSubject
代码中我们可以看见在初始化函数init
中什么也没做,但是它有一个on
函数并且可以看到PublishSubject
继承于SubjectType
public protocol SubjectType : 'ObservableType' {
/// The type of the observer that represents this subject.
///
/// Usually this type is type of subject itself, but it doesn‘t have to be.
associatedtype Observer: 'ObserverType'
@available(*, deprecated, message: Use `Observer` instead.)
typealias SubjectObserverType = Observer
/// Returns observer interface for subject.
///
/// - returns: Observer interface for subject.
func asObserver() -> Observer
我们可以看见SubjectType
继承ObservableType
,说明具有序列的特性,有subscribe
函数,同时又关联ObserverType
,具有观察者特性,具备on
函数。可以看出,它即是可观察序列(Observable
)又是观察者(Observer
)。
(二)、发送信号
publishSub.onNext(1)
会来到PublishSubject
的on
函数
public func on(_ event: Event<Element>) {
#if DEBUG
self._synchronizationTracker.register(synchronizationErrorMessage: .default)
defer { self._synchronizationTracker.unregister() }
#endif
dispatch(self._synchronized_on(event), event)
}
然后看见dispatch(self._synchronized_on(event), event)
,点进去
func _synchronized_on(_ event: Event<Element>) -> 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()
}
}
可以看到self._synchronized_on(event)
函数返回了 之前保存的观察者回调的收集,也就是下面函数的bag
:
func dispatch<Element>(_ bag: Bag<(Event<Element>) -> Void>, _ event: Event<Element>) {
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)
}
}
}
然后element(event)调用订阅时创建的观察者闭包,完成响应。
(三)进行订阅
publishSub.subscribe {print("订阅1:\($0)")}
.disposed(by: self.disposeBag)
接下来,会来到subscribe
函数,PublishSubject
对subscribe
函数进行了重写。
public override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
self._lock.lock()
let subscription = self._synchronized_subscribe(observer)
self._lock.unlock()
return subscription
}
为了保证顺序执行let subscription = self._synchronized_subscribe(observer)
前后加了锁。
func _synchronized_subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
if let stoppedEvent = self._stoppedEvent {
observer.on(stoppedEvent)
return Disposables.create()
}
if self._isDisposed {
observer.on(.error(RxError.disposed(object: self)))
return Disposables.create()
}
let key = self._observers.insert(observer.on)
return SubscriptionDisposable(owner: self, key: key)
}
经过了一些排空判断后,来到let key = self._observers.insert(observer.on)
,这个方法是向当前的observers
集合插入一个observer.on
mutating func insert(_ element: T) -> BagKey {
let key = _nextKey
_nextKey = BagKey(rawValue: _nextKey.rawValue &+ 1)
if _key0 == nil {
_key0 = key
_value0 = element
return key
}
_onlyFastPath = false
if _dictionary != nil {
_dictionary![key] = element
return key
}
if _pairs.count < arrayDictionaryMaxSize {
_pairs.append((key: key, value: element))
return key
}
_dictionary = [key: element]
return key
}
总结:
在订阅前发送.next
响应,observer
都还没有insert
,所以会接收不到响应。所以PublishSubject
的好处就是在需要用的时候才去订阅它,不用管之前的发送。