PublishSubject继承类和协议
public final class PublishSubject
: Observable
, SubjectType
, Cancelable
, ObserverType
, SynchronizedUnsubscribeType
Observable
: 被观察者Cancelable
: 可以被dispose
SynchronizedUnsubscribeType
可以取消订阅ObserverType
: 观察者-
SubjectType
:asObserver
subscribe
这个协议很好的描述对象即可以作为Observer
,也可以作为 Observerable
的特性
Observers Type
要理解PublishSubject
的核心,得先理解Observers
这个类型
typealias Observers = AnyObserver.s
extension AnyObserver {
/// Collection of `AnyObserver`s
typealias s = Bag<(Event) -> ()>
}
about Bag
Bag
: 是一个自定义容器,类似于Dictionary
, 之所以自定义实现主要是出于性能考虑,有兴趣的可以研究下,这里先留个坑
总的来说Observers 是一个 Bag 容器, 元素的类型为 (Event
订阅
public override func subscribe(_ observer: O) -> Disposable where O.E == Element {
_lock.lock()
let subscription = _synchronized_subscribe(observer)
_lock.unlock()
return subscription
}
func _synchronized_subscribe(_ observer: O) -> Disposable where O.E == E {
if let stoppedEvent = _stoppedEvent {
observer.on(stoppedEvent)
return Disposables.create()
}
if _isDisposed {
observer.on(.error(RxError.disposed(object: self)))
return Disposables.create()
}
let key = _observers.insert(observer.on)
return SubscriptionDisposable(owner: self, key: key)
}
一个同步锁, 几个异常处理, 剩下的就是核心代码:
let key = _observers.insert(observer.on)
: 将 Observer.on
函数塞入Bag
容器
return SubscriptionDisposable(owner: self, key: key)
返回SubscriptionDisposable
struct SubscriptionDisposable : Disposable {
private let _key: T.DisposeKey
private weak var _owner: T?
init(owner: T, key: T.DisposeKey) {
_owner = owner
_key = key
}
func dispose() {
_owner?.synchronizedUnsubscribe(_key)
}
}
SubscriptionDisposable
功能比较简单,只是对其进行简单的封装,那么这里为什么不让PublishSubject
直接支持Disposable
协议呢?这是为了保证设计的一致性,只有被订阅的Observable
才能被dispose
, 如果让PublishSubject
直接支持Disposable
协议就有损这个设计原则,固这里选择返回SubscriptionDisposable
on 事件
public func on(_ event: Event) {
#if DEBUG
_synchronizationTracker.register(synchronizationErrorMessage: .default)
defer { _synchronizationTracker.unregister() }
#endif
dispatch(_synchronized_on(event), event)
}
func _synchronized_on(_ event: Event) -> Observers {
_lock.lock(); defer { _lock.unlock() }
switch event {
case .next(_):
if _isDisposed || _stopped {
return Observers()
}
return _observers
case .completed, .error:
if _stoppedEvent == nil {
_stoppedEvent = event
_stopped = true
let observers = _observers
_observers.removeAll()
return observers
}
return Observers()
}
}
@inline(__always)
func dispatch(_ bag: Bag<(Event) -> ()>, _ event: Event) {
if bag._onlyFastPath {
bag._value0?(event)
return
}
let value0 = bag._value0
let dictionary = bag._dictionary
if let value0 = value0 {
value0(event)
}
let pairs = bag._pairs
for i in 0 ..< pairs.count {
pairs[i].value(event)
}
if let dictionary = dictionary {
for element in dictionary.values {
element(event)
}
}
}
这段逻辑复杂一点,先讲一下Bag容器
- 数据量为1 的时候 使用,直接使用
value0
存储元素 - 数据量在(1,30)的时候, 使用
ContiguousArray
存储元素,value0
仍然存储0号元素 - 超过30的数据,使用
Dictionary
存储超出的元素
理解了这些就明白dispatch
干了些啥了, 简单说就是
Bag.foreach { $0(event) }
一个PublishSubject
可以被多次订阅,每次订阅的时候将Observer.on
塞入Bag
容器,在执行PublishSubject.on
事件的时候, 会执行所有Observer
的on
事件。
Unsubscribe
func synchronizedUnsubscribe(_ disposeKey: DisposeKey) {
_lock.lock()
_synchronized_unsubscribe(disposeKey)
_lock.unlock()
}
func _synchronized_unsubscribe(_ disposeKey: DisposeKey) {
_ = _observers.removeKey(disposeKey)
}
这个就很简单,unsubscribe
的时候,将Observer
从Bag
容器中移除就可以。