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)
}
}
AnonymousObservable
Inside the create function, an anonymous observable sequence object is actually created . The previous closure is also AnonymousObservable
used 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. eventHandler
What is this? Isn't it the closure of the processing AnonymousObserver
saved 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!