RxSwift官方使用示例之<使用Subjects>

avatar
iOS 开发工程师 @抖音视界有限公司

本文是示例主要来自于官方的实例代码,可从这里下载 ,实例代码稍有改动。其中的图片来自于reactivex.io/

本文主要的作用是查看实例代码并查看对应实例代码的效果,不需要运行项目

操作符目录

debug 操作符会打印所有的 subscriptions, events, disposals

PublishSubject

示例

在订阅时向所有观察者广播新事件

let disposeBag = DisposeBag()
let subject = PublishSubject<String>()

subject.subscribe { print("A:", $0) }.disposed(by: disposeBag)
// 此时有1个订阅者A,会给A发送事件
subject.onNext("🐶")
subject.onNext("🐱")

subject.subscribe { print("B:", $0) }.disposed(by: disposeBag)
// 此时有2个订阅者A和B,会给A和B分别发送事件
subject.onNext("🅰️")
subject.onNext("🅱️")

打印

A: next(🐶)
A: next(🐱)
A: next(🅰️)
B: next(🅰️)
A: next(🅱️)
B: next(🅱️)

核心源码

final class PublishSubject<Element>: Observable<Element>, SubjectType, Cancelable, ObserverType, SynchronizedUnsubscribeType {
    typealias SubjectObserverType = PublishSubject<Element>
    typealias Observers = AnyObserver<Element>.s
    typealias DisposeKey = Observers.KeyType
    
    private let lock = SpinLock()
    private var disposed = false
    private var observers = Observers()
    private var stopped = false
    private var stoppedEvent: Event<Element>?
    
    var hasObservers: Bool {
        lock.performLocked { self.observers.count > 0 }
    }
    
    var isDisposed: Bool { disposed }
    
    override init() {
        super.init()
    }
    // 2. 给所有的订阅者发送消息
    func on(_ event: Event<Element>) {
        dispatch(synchronized_on(event), event)
    }
    
    func synchronized_on(_ event: Event<Element>) -> Observers {
        lock.lock(); defer { self.lock.unlock() }
        switch event {
        case .next:
            if stopped || isDisposed {
                return Observers()
            }
            return observers
        case .completed, .error:
            if stoppedEvent == nil {
                stoppedEvent = event
                stopped = true
                let observers = self.observers
                self.observers.removeAll()
                return observers
            } else {
                return Observers()
            }
        }
    }
    
    // 1. 添加一个订阅者,会放到 observers 中,等待发送事件
    override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Element == Observer.Element {
        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)
    }
    
    func synchronizedUnsubscribe(_ disposeKey: Observers.KeyType) {
        lock.performLocked { _ = self.observers.remove(disposeKey) }
    }
    
    func asObserver() -> PublishSubject<Element> {
        self
    }
    
    func dispose() {
        lock.performLocked {
            self.disposed = true
            self.observers.removeAll()
            self.stoppedEvent = nil
        }
    }
}

ReplaySubject

示例

向所有订阅者广播新事件,并将指定的 bufferSize 数量的先前事件广播给新订阅者

let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 1)

subject.subscribe { print("A:", $0) }.disposed(by: disposeBag)
// 此时有1个订阅者A,会给A发送事件
subject.onNext("🐶")
subject.onNext("🐱")

subject.subscribe { print("B:", $0) }.disposed(by: disposeBag)
// 此时有2个订阅者A和B,会给A和B分别发送事件,但会先给新订阅者B发送之前缓存的事件🐱
subject.onNext("🅰️")
subject.onNext("🅱️")

打印

A: next(🐶)
A: next(🐱)
B: next(🐱)
A: next(🅰️)
B: next(🅰️)
A: next(🅱️)
B: next(🅱️)

核心源码

  • 本质就是会在内存中最多保存 bufferSize 个元素,给新订阅者重新发一遍这些事件
  • 之后的新事件会给所有的订阅者发送
class ReplaySubject<Element>: Observable<Element>, SubjectType, ObserverType, Disposable {
    typealias SubjectObserverType = ReplaySubject<Element>
    typealias Observers = AnyObserver<Element>.s
    typealias DisposeKey = Observers.KeyType
    
    fileprivate let lock = SpinLock()
    fileprivate var isDisposed = false
    fileprivate var stopped = false
    fileprivate var observers = Observers()
    fileprivate var stoppedEvent: Event<Element>? {
        didSet {
            stopped = stoppedEvent != nil
        }
    }
    
    var isStoped: Bool { stopped }
    
    func unsubscribe(_ key: DisposeKey) {
        rxAbstractMethod()
    }
    
    func on(_ event: Event<Element>) {
        rxAbstractMethod()
    }
    
    func asObserver() -> ReplaySubject<Element> {
        self
    }
    
    func dispose() {
    }
    
    static func create(bufferSize: Int) -> ReplaySubject<Element> {
        if bufferSize == 1 {
            return ReplayOne<Element>()
        } else {
            return ReplayMany<Element>(bufferSize: bufferSize)
        }
    }
    
    static func createUnbounded() -> ReplaySubject<Element> {
        ReplayAll()
    }
}

private class ReplayBufferBase<Element>: ReplaySubject<Element>, SynchronizedUnsubscribeType {
    func trim() {
        rxAbstractMethod()
    }
    
    func addValueToBuffer(_ value: Element) {
        rxAbstractMethod()
    }
    
    func replayBuffer<Observer: ObserverType>(_ observer: Observer) where Observer.Element == Element {
        rxAbstractMethod()
    }
    
    override func on(_ event: Event<Element>) {
        dispatch(synchronized_on(event), event)
    }
    
    func synchronized_on(_ event: Event<Element>) -> Observers {
        lock.lock(); defer { lock.unlock() }
        if isStoped || isDisposed {
            return Observers()
        }
        switch event {
        case .next(let value):
            addValueToBuffer(value)
            trim()
            return observers
        case .error, .completed:
            stoppedEvent = event
            trim()
            let observers = self.observers
            self.observers.removeAll()
            return observers
        }
    }
    
    override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Element == Observer.Element {
        lock.performLocked {
            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)
            }
        }
    }
    
    func synchronizedUnsubscribe(_ disposeKey: DisposeKey) {
        lock.performLocked {
            self.synchronized_unsubscribe(disposeKey)
        }
    }
    
    func synchronized_unsubscribe(_ disposeKey: DisposeKey) {
        if isDisposed { return }
        _ = observers.remove(disposeKey)
    }
    
    override func dispose() {
        super.dispose()
        
        lock.performLocked {
            self.synchronizedDispose()
        }
    }
    
    func synchronizedDispose() {
        self.isDisposed = true
        self.observers.removeAll()
    }
    
    
}

private final class ReplayOne<Element>: ReplayBufferBase<Element> {
    private var value: Element?
    
    override func trim() {
    }
    
    override func addValueToBuffer(_ value: Element) {
        self.value = value
    }
    
    override func replayBuffer<Observer: ObserverType>(_ observer: Observer) where Element == Observer.Element {
        if let value = value {
            observer.on(.next(value))
        }
    }
    
    override func synchronizedDispose() {
        super.synchronizedDispose()
        value = nil
    }
}

private class ReplayManyBase<Element>: ReplayBufferBase<Element> {
    fileprivate var queue: Queue<Element>
    
    init(queueSize: Int) {
        queue = Queue<Element>(capacity: queueSize + 1)
    }
    
    override func addValueToBuffer(_ value: Element) {
        queue.enqueue(value)
    }
    
    override func replayBuffer<Observer: ObserverType>(_ observer: Observer) where Element == Observer.Element {
        for item in queue {
            observer.on(.next(item))
        }
    }
    
    override func synchronizedDispose() {
        super.synchronizedDispose()
        queue = Queue<Element>(capacity: 0)
    }
}

private final class ReplayMany<Element>: ReplayManyBase<Element> {
    private let bufferSize: Int
    init(bufferSize: Int) {
        self.bufferSize = bufferSize
        super.init(queueSize: bufferSize)
    }
    
    override func trim() {
        while queue.count > bufferSize {
            _ = queue.dequeue()
        }
    }
}

private final class ReplayAll<Element>: ReplayManyBase<Element> {
    init() {
        super.init(queueSize: 0)
    }
    override func trim() {
    }
}

BehaviorSubject

示例

向所有订阅者广播新事件,并向新订阅者广播最新(或初始)值

let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "🔴")

subject.subscribe { print("A:", $0) }.disposed(by: disposeBag)
// 此时有1个订阅者A,会给A发送事件,并先发送初始值🔴
subject.onNext("🐶")
subject.onNext("🐱")

subject.subscribe { print("B:", $0) }.disposed(by: disposeBag)
// 此时有2个订阅者A和B,会给A和B分别发送事件
// 但会先给新订阅者B发送之前缓存的事件🐱
subject.onNext("🅰️")
subject.onNext("🅱️")

subject.subscribe { print("C:", $0) }.disposed(by: disposeBag)
// 此时有3个订阅者A、B和C,会给A、B和C分别发送事件
// 但会先给新订阅者C发送之前缓存的事件🅱️
subject.onNext("🍐")
subject.onNext("🍊")

打印

A: next(🔴)
A: next(🐶)
A: next(🐱)
B: next(🐱)
A: next(🅰️)
B: next(🅰️)
A: next(🅱️)
B: next(🅱️)
C: next(🅱️)
A: next(🍐)
B: next(🍐)
C: next(🍐)
A: next(🍊)
B: next(🍊)
C: next(🍊)

核心源码

final class BehaviorSubject<Element>: Observable<Element>, SubjectType, ObserverType, SynchronizedUnsubscribeType, Cancelable {
    typealias SubjectObserverType = PublishSubject<Element>
    typealias Observers = AnyObserver<Element>.s
    typealias DisposeKey = Observers.KeyType
    
    private let lock = SpinLock()
    private var disposed = false
    private var observers = Observers()
    private var stoppedEvent: Event<Element>?
    private var element: Element
    
    var hasObservers: Bool { lock.performLocked { self.observers.count > 0 } }
    
    var isDisposed: Bool { disposed }
    
    init(value: Element) {
        element = value
    }
    
    func value() throws -> Element {
        lock.lock(); defer { lock.unlock() }
        
        if isDisposed {
            throw RxError.disposed(object: self)
        }
        
        if let error = stoppedEvent?.error {
            throw error
        }
        return element
    }
    
    // 2. 给所有的订阅者发送事件
    func on(_ event: Event<Element>) {
        dispatch(synchronized_on(event), event)
    }
    
    func synchronized_on(_ event: Event<Element>) -> Observers {
        lock.lock(); defer { lock.unlock() }
        if stoppedEvent != nil || isDisposed {
            return Observers()
        }
        switch event {
        case .next(let e):
            element = e
        case .error, .completed:
            stoppedEvent = event
        }
        return observers
    }
    
    override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Element == Observer.Element {
        lock.lock(); defer { lock.unlock() }
        if isDisposed {
            observer.onError(RxError.disposed(object: self))
            return Disposables.create()
        }
        if let stoppedEvent = stoppedEvent {
            observer.on(stoppedEvent)
            return Disposables.create()
        }
        
        let key = observers.insert(observer.on)
        // 1. 订阅的时候会发之前保存的元素
        observer.on(.next(self.element))
        return SubscriptionDisposable(owner: self, key: key)
    }
    
    func synchronizedUnsubscribe(_ disposeKey: DisposeKey) {
        lock.performLocked {
            if self.isDisposed { return }
            
            _ = self.observers.remove(disposeKey)
        }
    }
    
    func asObserver() -> BehaviorSubject<Element> {
        self
    }
    
    func dispose() {
        lock.performLocked {
            self.disposed = true
            self.observers.removeAll()
            self.stoppedEvent = nil
        }
    }
}