(十四)RxSwift之subscribeOn

315 阅读3分钟

subscribeOn指定 Observable 在那个 Scheduler 执行

下面让我们一起来看一下subscribeOn内部是如何实现的

先来看一段简单的代码

Observable.of(1,2,3,4,5)
    .subscribeOn(SerialDispatchQueueScheduler.init(internalSerialQueueName: "subscribeOnSerial"))
    .subscribe{print("subscribeOn",$0,Thread.current)}
    .disposed(by: self.bag)

一句一句来解析:

  • (一)Observable.of(1,2,3,4,5)

public static func of(_ elements: Element ..., scheduler: ImmediateSchedulerType = CurrentThreadScheduler.instance) -> Observable<Element> {
    return ObservableSequence(elements: elements, scheduler: scheduler)
}

这段代码会要求我们传入一些元素,然后会给一个默认的schedulerCurrentThreadScheduler 会返回一个ObservableSequence类型的序列

final private class ObservableSequence<Sequence: Swift.Sequence>: Producer<Sequence.Element> {
    fileprivate let _elements: Sequence
    fileprivate let _scheduler: ImmediateSchedulerType

    init(elements: Sequence, scheduler: ImmediateSchedulerType) {
        self._elements = elements//1 2 3 4 5
        self._scheduler = scheduler//<CurrentThreadScheduler: 0x60000255c010>
    }

    override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
        let sink = ObservableSequenceSink(parent: self, observer: observer, cancel: cancel)
        let subscription = sink.run()
        return (sink: sink, subscription: subscription)
    }
}

该序列初始化时保存了原序列(elements) 和 调度环境(scheduler),并继承了Producer,实现了run方法。

  • (二).subscribeOn(SerialDispatchQueueScheduler.init(internalSerialQueueName: "subscribeOnSerial"))

public class SerialDispatchQueueScheduler : SchedulerType {

    let configuration: DispatchQueueConfiguration
    init(serialQueue: DispatchQueue, leeway: DispatchTimeInterval = DispatchTimeInterval.nanoseconds(0)) {
        self.configuration = DispatchQueueConfiguration(queue: serialQueue, leeway: leeway)
    }

    public convenience init(internalSerialQueueName: String, serialQueueConfiguration: ((DispatchQueue) -> Void)? = nil, leeway: DispatchTimeInterval = DispatchTimeInterval.nanoseconds(0)) {
        let queue = DispatchQueue(label: internalSerialQueueName, attributes: [])
        serialQueueConfiguration?(queue)
        self.init(serialQueue: queue, leeway: leeway)
    }
}

使用便利构造器初始化一个串行队列,并调用self.init将队列queue 和 延迟时间 leeway 保存在 self.configuration 中。 接下来,会带着创建好的队列来到 SubscribeOn 函数:

final private class SubscribeOn<Ob: ObservableType>: Producer<Ob.Element> {
    let source: Ob
    let scheduler: ImmediateSchedulerType
    
    init(source: Ob, scheduler: ImmediateSchedulerType) {
        self.source = source//<ObservableSequence<Array<Int>>: 0x6000032da2c0>
        self.scheduler = scheduler//<SerialDispatchQueueScheduler: 0x6000029d9140>
    }
    
    override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Ob.Element {
        let sink = SubscribeOnSink(parent: self, observer: observer, cancel: cancel)
        let subscription = sink.run()
        return (sink: sink, subscription: subscription)
    }
}

SubscribeOn 在初始化的时候保存了源函数(Observable.of(1,2,3,4,5))和我们初始化的串行队列(SerialDispatchQueueScheduler),并且同样继承了Producer,实现了自己的run方法。

  • (三).subscribe{print("subscribeOn",$0,Thread.current)}

由于SubscribeOn继承Producer,所以回来到Producersubscribe

override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
    if !CurrentThreadScheduler.isScheduleRequired {
        // The returned disposable needs to release all references once it was disposed.
        let disposer = SinkDisposer()
        let sinkAndSubscription = self.run(observer, cancel: disposer)
        disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

        return disposer
    }
    else {
        return CurrentThreadScheduler.instance.schedule(()) { _ in
            let disposer = SinkDisposer()
            let sinkAndSubscription = self.run(observer, cancel: disposer)
            disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

            return disposer
        }
    }
}

由于当前线程没有被绑定,所以走else的方法,会携带闭包来到当前线程的schedule方法。

public func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
    if CurrentThreadScheduler.isScheduleRequired {
        CurrentThreadScheduler.isScheduleRequired = false//绑定线程

        let disposable = action(state)//state 外界闭包

        defer {//延迟执行
            CurrentThreadScheduler.isScheduleRequired = true
            CurrentThreadScheduler.queue = nil
        }

        guard let queue = CurrentThreadScheduler.queue else {
            return disposable
        }

        while let latest = queue.value.dequeue() {
            if latest.isDisposed {
                continue
            }
            latest.invoke()
        }

        return disposable
    }

    let existingQueue = CurrentThreadScheduler.queue

    let queue: RxMutableBox<Queue<ScheduledItemType>>
    if let existingQueue = existingQueue {//当前线程存在队列
        queue = existingQueue
    }
    else {//当前线程不存在队列,初始化一个
        queue = RxMutableBox(Queue<ScheduledItemType>(capacity: 1))
        CurrentThreadScheduler.queue = queue
    }

    let scheduledItem = ScheduledItem(action: action, state: state)
    queue.value.enqueue(scheduledItem)

    return scheduledItem
}

这个方法先绑定了当前线程,然后回去执行schedule方法带过来的外界闭包

return CurrentThreadScheduler.instance.schedule(()) { _ in
    let disposer = SinkDisposer()
    let sinkAndSubscription = self.run(observer, cancel: disposer)
    disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

    return disposer
}

然后 sink.run 又回到了SubscribeOnrun方法中

final private class SubscribeOn<Ob: ObservableType>: Producer<Ob.Element> {
    let source: Ob
    let scheduler: ImmediateSchedulerType
    
    init(source: Ob, scheduler: ImmediateSchedulerType) {
        self.source = source//<ObservableSequence<Array<Int>>: 0x6000032da2c0>
        self.scheduler = scheduler//<SerialDispatchQueueScheduler: 0x6000029d9140>
    }
    
    override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Ob.Element {
        let sink = SubscribeOnSink(parent: self, observer: observer, cancel: cancel)
        let subscription = sink.run()
        return (sink: sink, subscription: subscription)
    }
}

然后会SubscribeOnSink的初始化方法,然后走run方法

final private class SubscribeOnSink<Ob: ObservableType, Observer: ObserverType>: Sink<Observer>, ObserverType where Ob.Element == Observer.Element {
    typealias Element = Observer.Element 
    typealias Parent = SubscribeOn<Ob>
    
    let parent: Parent
    
    init(parent: Parent, observer: Observer, cancel: Cancelable) {
        self.parent = parent//<SubscribeOn<Observable<Int>>: 0x6000032dabc0>
        super.init(observer: observer, cancel: cancel)//on赋值会来到下面的on方法
    }
    
    func on(_ event: Event<Element>) {
        self.forwardOn(event)
        
        if event.isStopEvent {
            self.dispose()
        }
    }
    
    func run() -> Disposable {
        let disposeEverything = SerialDisposable()
        let cancelSchedule = SingleAssignmentDisposable()
        
        disposeEverything.disposable = cancelSchedule
        //self.parent.scheduler <SerialDispatchQueueScheduler: 0x6000029d9140>
        let disposeSchedule = self.parent.scheduler.schedule(()) { _ -> Disposable in
            let subscription = self.parent.source.subscribe(self)
            disposeEverything.disposable = ScheduledDisposable(scheduler: self.parent.scheduler, disposable: subscription)
            return Disposables.create()
        }

        cancelSchedule.setDisposable(disposeSchedule)
    
        return disposeEverything
    }
}

self.parent.scheduler.scheduleSerialDispatchQueueScheduler,携带闭包来到SerialDispatchQueueSchedulerschedule方法。

public final func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
    return self.scheduleInternal(state, action: action)
}

func scheduleInternal<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
    return self.configuration.schedule(state, action: action)
}

接下来会带着一开始初始化串行队列给self.configuration赋值时保存的队列和延迟时间来到configurationschedule方法。

func schedule<StateType>(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
    let cancel = SingleAssignmentDisposable()

    self.queue.async {
        if cancel.isDisposed {
            return
        }
        cancel.setDisposable(action(state))
    }

    return cancel
}

会看到我们初始化队列,异步执行外界闭包

let disposeSchedule = self.parent.scheduler.schedule(()) { _ -> Disposable in
    let subscription = self.parent.source.subscribe(self)
    disposeEverything.disposable = ScheduledDisposable(scheduler: self.parent.scheduler, disposable: subscription)
    return Disposables.create()
}

self.parent.source.subscribe(self)会由源序列来订阅当前的sink,看到这里我们就知道了,源序列在我们特定的队列中进行订阅。

总结

subscribeOn为我们创建一个中间层序列subscribeOn,然后并没有SubscribeOn函数的run方法中直接进行源序列的订阅,而是在SubscribeOnSinkrun方法中保证了源序列在特定线程中的订阅。