Advanced RXSwift: Analysis of the underlying core logic of RXSwift

Introduction to basic usage

 

In the previous RXSwift basic introduction, we already know that the basic usage of RXSwift is roughly divided into three steps:

1. Create an observable sequence

2. Listen to the sequence (subscribe to the signal sent by the sequence)

3. Destruction sequence

//创建可观察序列
let ob = Observable.create { (observer) -> Disposable in
    //发送信号
    observer.onNext("RXSwift核心逻辑")
    observer.onCompleted()

    return Disposables.create()
}
//订阅信号
let _ = ob.subscribe(onNext: { (text) in
    print("订阅:\(text)")
}, onError: { (error) in
    print(error)
}, onCompleted: {
    print("完成")
}) {
    print("销毁")
}

控制台输出:

订阅:RXSwift核心逻辑
完成
销毁

Analysis of the underlying process

1. Class inheritance relationship

 2. Underlying process

1. Create an observable sequence

Observable creates an observable sequence AnoymousObservable through the create function (inherited from Producer, Producer complies with the ObservableType protocol), AnoymousObservable saves the closure passed by the create function (including onNext) through the subscribeHandler attribute, and the create function returns the AnoymousObservable object

create function:

extension ObservableType {
    // MARK: create
    public static func create(_ subscribe: @escaping (AnyObserver<Element>) -> Disposable) -> Observable<Element> {
        AnonymousObservable(subscribe)
    }
}

AnonymousObservableInside the create function, an anonymous observable sequence object is actually created . The previous closure is also AnonymousObservableused for object initialization.

final private class AnonymousObservable<Element>: Producer<Element> {
    typealias SubscribeHandler = (AnyObserver<Element>) -> Disposable

    let subscribeHandler: SubscribeHandler

    init(_ subscribeHandler: @escaping SubscribeHandler) {
        self.subscribeHandler = subscribeHandler
    }

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

2. Subscribe to signals

AnoymousObservable calls the subscribe method to pass the closure. Because the parent class complies with the ObservableType protocol, AnoymousObservable also complies with this protocol, so the subscribe method in the ObservableType protocol is called. Create an AnoymousObserver object in the subscribe method (what is an observer, comply with the ObserverType protocol), and return Disposable.

subscribe function:

public func subscribe(
        onNext: ((Element) -> Void)? = nil,
        onError: ((Swift.Error) -> Void)? = nil,
        onCompleted: (() -> Void)? = nil,
        onDisposed: (() -> Void)? = nil
    ) -> Disposable {
            let disposable: Disposable
            
            if let disposed = onDisposed {
                disposable = Disposables.create(with: disposed)
            }
            else {
                disposable = Disposables.create()
            }
            
            #if DEBUG
                let synchronizationTracker = SynchronizationTracker()
            #endif
            
            let callStack = Hooks.recordCallStackOnError ? Hooks.customCaptureSubscriptionCallstack() : []
            
            let observer = AnonymousObserver<Element> { event in
                
                #if DEBUG
                    synchronizationTracker.register(synchronizationErrorMessage: .default)
                    defer { synchronizationTracker.unregister() }
                #endif
                
                switch event {
                case .next(let value):
                    onNext?(value)
                case .error(let error):
                    if let onError = onError {
                        onError(error)
                    }
                    else {
                        Hooks.defaultErrorHandler(callStack, error)
                    }
                    disposable.dispose()
                case .completed:
                    onCompleted?()
                    disposable.dispose()
                }
            }
            return Disposables.create(
                self.asObservable().subscribe(observer),
                disposable
            )
    }

Call Producer's subscribe in the Disposables.create method, and the final observer (AnoymousObserver) is placed in the subscribe. 

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
            }
        }
    }

Call the run method of AnonymousObservable in Producer's subscribe

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

The self passed in in sink.run( self ) is AnonymousObservable, and then call parent.subscribeHandler(AnyObserver( self )),

func run(_ parent: Parent) -> Disposable {
        parent.subscribeHandler(AnyObserver(self))
}

The parent is AnonymousObservable, calling the subscribeHandler callback stored in AnonymousObservable. The observer.onNext method will be triggered here. The observer here is AnyObserver. AnyObserver complies with the ObserverType protocol, so the onNext method of ObserverType is called.

extension ObserverType {

    public func onNext(_ element: Element) {
        self.on(.next(element))
    }
    
    public func onCompleted() {
        self.on(.completed)
    }
    
    public func onError(_ error: Swift.Error) {
        self.on(.error(error))
    }
}

The on method of Anyobserver is triggered

public func on(_ event: Event<Element>) {
        self.observer(event)
 }

AnyObserver left self .observer = observer.on during initialization, observer.on is the on method of AnonymousObservableSink,

func on(_ event: Event<Element>) {
        #if DEBUG
            self.synchronizationTracker.register(synchronizationErrorMessage: .default)
            defer { self.synchronizationTracker.unregister() }
        #endif
        switch event {
        case .next:
            if load(self.isStopped) == 1 {
                return
            }
            self.forwardOn(event)
        case .error, .completed:
            if fetchOr(self.isStopped, 1) == 0 {
                self.forwardOn(event)
                self.dispose()
            }
        }
  }

Then call the forwardOn method of the Sink base class,

final func forwardOn(_ event: Event<Observer.Element>) {
        #if DEBUG
            self.synchronizationTracker.register(synchronizationErrorMessage: .default)
            defer { self.synchronizationTracker.unregister() }
        #endif
        if isFlagSet(self.disposed, 1) {
            return
        }
        self.observer.on(event)
    }

Call self.observer.on , the Observer of the sink is AnonymousObserver, AnonymousObserver has no on method, so the on method of the base class ObserverBase of AnonymousObserver will be called, and the onCore method is called in the on method.

func on(_ event: Event<Element>) {
        switch event {
        case .next:
            if load(self.isStopped) == 0 {
                self.onCore(event)
            }
        case .error, .completed:
            if fetchOr(self.isStopped, 1) == 0 {
                self.onCore(event)
            }
        }
    }

Then call the onCore method of AnonymousObserver, and call the eventHandler that stores the ONext callback in the onCore method. eventHandlerWhat is this? Isn't it the closure of the processing AnonymousObserversaved during initialization ! subscribe闭包So it can be triggered create闭包, and finally the callback passed by subscribe is called, and the process is completed.observer.onNext("...")subscribe闭包

override func onCore(_ event: Event<Element>) {
        self.eventHandler(event)
    }

3. Destruction sequence

In the subscribe function, we can see that the corresponding disposable destruction object is established

let disposable: Disposable
            
if let disposed = onDisposed {
     disposable = Disposables.create(with: disposed)
   }
    else {
           disposable = Disposables.create()
 }

The corresponding destroy method will be called when an error occurs or when it is completed

                case .error(let error):
                   if let onError = onError {
                        onError(error)
                    }
                    else {
                        Hooks.defaultErrorHandler(callStack, error)
                    }
                    disposable.dispose()
                case .completed:
                    onCompleted?()
                    disposable.dispose()
                }

Next, let's see what the create function does

public static func create(with dispose: @escaping () -> Void) -> Cancelable {
        AnonymousDisposable(disposeAction: dispose)
    }

The object AnonymousDisposable used to execute the dispose callback function is created, and the dispose function callback is executed in the following function segment

fileprivate func dispose() {
        if fetchOr(self.disposed, 1) == 0 {
            if let action = self.disposeAction {
                self.disposeAction = nil
                action()
            }
        }
    }

The entire destruction process is connected in series with the code Disposables.create(self.asObservable().subscribe(observer),disposable). Follow up and see that there is a binary destroyer BinaryDisposable(disposable1, disposable2), here is the corresponding Destroy method dispose

func dispose() {
        if fetchOr(self.disposed, 1) == 0 {
            self.disposable1?.dispose()
            self.disposable2?.dispose()
            self.disposable1 = nil
            self.disposable2 = nil
        }
    }

We can know that disposable2 is AnonymousDisposable, which is related to the destruction callback, so what is disposable1? According to the above code, we enter the Producer class

let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)

return disposer

The dipose destruction method corresponding to SinkDisposer destroys both the subscribe callback function and the sink pipeline, disconnecting the entire process.

func dispose() {
        let previousState = fetchOr(self.state, DisposeState.disposed.rawValue)

        if (previousState & DisposeState.disposed.rawValue) != 0 {
            return
        }

        if (previousState & DisposeState.sinkAndSubscriptionSet.rawValue) != 0 {
            guard let sink = self.sink else {
                rxFatalError("Sink not set")
            }
            guard let subscription = self.subscription else {
                rxFatalError("Subscription not set")
            }

            sink.dispose()
            subscription.dispose()

            self.sink = nil
            self.subscription = nil
        }
    }

 How to pass the sink pipeline and subscribe callback function, mainly through the method in the above code: setSinkAndSubscription

func setSinkAndSubscription(sink: Disposable, subscription: Disposable) {
        self.sink = sink
        self.subscription = subscription

        let previousState = fetchOr(self.state, DisposeState.sinkAndSubscriptionSet.rawValue)
        if (previousState & DisposeState.sinkAndSubscriptionSet.rawValue) != 0 {
            rxFatalError("Sink and subscription were already set")
        }

        if (previousState & DisposeState.disposed.rawValue) != 0 {
            sink.dispose()
            subscription.dispose()
            self.sink = nil
            self.subscription = nil
        }
    }

This completes the entire destruction process.


In summary, the underlying code of the entire process of creating an observable sequence -> listening sequence (subscribing to the signal sent by the sequence) -> destroying the sequence has been analyzed. If you find it useful, click a star!

Guess you like

Origin blog.csdn.net/weixin_42433480/article/details/129682431