阅读 323

Rx的Observable.create干了啥?

前言

最近在看一些Rx源码,一直以来Rx的源码给人的感觉都是比较绕的,基于这个问题笔者想从比较简单Rx代码出发,尝试归纳出其源码封装的套路。本文会通过RxJava及RxSwift的源码来总结Observable.create到底干了啥,以此来总结一些看Rx源码的套路。 由于涉及到两个版本的Rx,照顾到可能不是每个人都同时掌握这两门语言,故文章的部分内容可能会有些许雷同,大家可以通过子标题阅读自己熟悉的语言版本(ps:本文Rx源码基于RxJava 2.1.16,RxSwift 5.1.1)。 说到Rx就能联想响应式编程思想,这里转载一篇个人觉得分析传统面向对象编程思想与响应式编程思想比较好的文章:【响应式编程的思维艺术】响应式Vs面向对象,文中是基于RxJs介绍的,这里理解其思想即可。

Rx基本概念

Rx的代码调用这里可以简单归纳为3个阶段: 事件产生、事件加工、事件消费

create() , just() , from()   等                        ---   事件产生
map() , filter()  等                                   ---   事件加工
subscribe()                                            ---   事件消费
复制代码
  • 事件产生:开发者调用onNext、onError...等事件流的地方。
  • 事件加工:Rx丰富操作符,对产生的数据流进行二次创作,譬如map的转换、filter的过滤等。
  • 事件消费:订阅对于onNext/onError/onCompleted/onDisposed的自定义实现响应处理。

以下为基于RxJava和RxSwift编写的Observable.create代码,其中就经历了事件的产生、加工及消费: ps:RxJava的示例代码均为Kotlin编写,下文一致。

Observable.create<String> {  // it::class.java == ObservableEmitter
    Log.d(TAG, "事件产生线程:${Thread.currentThread().name}")
    it.onNext("I'm ")
    it.onComplete()
}.map {
    Log.d(TAG, "事件产生线程:${Thread.currentThread().name}")
    return@map it + "rx"
}.subscribe { // onNext
    Log.d(TAG, "事件消费线程:${Thread.currentThread().name}")
    Log.d(TAG, it)
}
复制代码
Observable<String>.create { (ob) -> Disposable in
            print("事件产生线程:\(Thread.current.description)")
            ob.onNext("I'm ")
            ob.onCompleted()
            return Disposables.create()
        }
        .map({ (str) -> String in
            print("事件加工线程:\(Thread.current.description)")
            return str + "rx"
        })
        .subscribe(onNext: { (str) in
            print("事件消费线程:\(Thread.current.description)")
            print(str)
        }, onError: nil, onCompleted: nil, onDisposed: nil)
复制代码

ps: 这里插播一个题外话,上述示例可以看到输出结果显示函数的执行线程都为主线程。可能有人会认为Rx默认是多线程的,这个例子就告诉我们Rx默认都是在你调用subscribe时的线程执行,譬如这里就是主线程(main)。唯有subscribeOn或observeOn具有线程调度的能力。关于这两个操作符的解析还有线程调度的问题将在后续文章讲到。

接下来就让我们来看看Observable.create中事件产生->消费是怎样实现的,这里为了降低代码理解难度,先忽略掉事件加工阶段。 温馨提示:因为Rx源码涉及的自定义类型较多,文字描述可能不够清晰造成逻辑混乱,可对照着源码阅读。

RxJava

Observable.create<String>

接下来的代码解析会基于以下代码进行:

Observable.create<String> {  // it::class.java = ObservableEmitter
    Log.d(TAG, "事件产生线程:${Thread.currentThread().name}")
    it.onNext("Hello world")
    it.onComplete()
}.subscribe { // onNext
    Log.d(TAG, "事件消费线程:${Thread.currentThread().name}")
    Log.d(TAG, it)
}
复制代码

在解析代码之前, _大家可以先对ObservableCreate、subscribeActual、subscribe这几个关键词有印象,后续会有详细的解析。

阶段1:创建/定义

该小节主要解析的是调用Observable.create时的代码。

// Observable.java
public static Observable create(ObservableOnSubscribe source) {
    ObjectHelper.requireNonNull(source, "source is null");
    return RxJavaPlugins.onAssembly(new ObservableCreate(source));
}
复制代码
// ObservableCreate.java
public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe source;

    public ObservableCreate(ObservableOnSubscribe source) {
        this.source = source;
    }
...
}
复制代码
  • Observable.create方法中其实就是 创建一个ObservableCreate对象,Rxjava里面的一个可订阅的对象。 在Rxjava中所有的可订阅对象都与Observable类有关,它是一个抽象类。这里的RxJavaRlugins是Rxjava里的一个用于hook的辅助类,里面可以定义一些hook。可参考RxJavaRlugins.java。
  • ObservableCreate类的创建其实就是将最初通过调用Observable.create传入的ObservableOnSubscribe对象(ps: ObservableOnSubscribe是一个接口,实现匿名对象的方法就是开发者进行事件产生的过程,onNext...)为自己的成员变量,以便后续开发者调用触发subscribe时进行操作。
  • 值得一提的是Observable.create方法中传入的ObservableOnSubscribe对象,是一个接口实现类,事件产生就是发生在我们定义的subscribe方法:
// ObservableOnSubscribe.java
public interface ObservableOnSubscribe<T> {
    void subscribe( ObservableEmitter emitter) throws Exception;
}
复制代码

上述的解析内容可见源码:

阶段2:订阅

当我们通过Observable.create定义好事件产生部分,紧接着调用subscribe方法即可触发订阅逻辑。以下部分会带着大家看看这部分的源码。

1、当调用ObservableCreate.subscribe后,会先对我们传入onNext、onError等回调进行一次对象封装,这里会实例一个LambdaObserver。实际上外部我们传入onNext等回调是Consumer接口实现(ps: onComplete回调是Action接口的实现)。然后再用这个LambdaObserver对象往下调用其自身(Observable.java)的subscribe重载方法。

// Observable.java
public final Disposable subscribe(Consumersuper T> onNext, Consumersuper Throwable> onError,
        Action onComplete, Consumersuper Disposable> onSubscribe) {
    ObjectHelper.requireNonNull(onNext, "onNext is null");
    ObjectHelper.requireNonNull(onError, "onError is null");
    ObjectHelper.requireNonNull(onComplete, "onComplete is null");
    ObjectHelper.requireNonNull(onSubscribe, "onSubscribe is null");

    LambdaObserver ls = new LambdaObserver(onNext, onError, onComplete, onSubscribe);

    subscribe(ls);

    return ls;
}
复制代码

上述代码发生在ObservableCreate的父类Observable.java 12013行

2、重载的subscribe方法依然在父类Observable内,其最终的目的是 将1中的LambdaObserver对象调用subscribeActual方法,顺带一提,subscribeActual方法是抽象方法,其实现在 子类ObservableCreate

// Observable.java
public final void subscribe(Observersuper T> observer) {
    ObjectHelper.requireNonNull(observer, "observer is null");
    try {
        observer = RxJavaPlugins.onSubscribe(this, observer);

        ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");

        subscribeActual(observer);
    } catch (NullPointerException e) {
        throw e;
    } catch (Throwable e) {
        Exceptions.throwIfFatal(e);

        RxJavaPlugins.onError(e);

        NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
        npe.initCause(e);
        throw npe;
    }
}
...

protected abstract void subscribeActual(Observersuper T> observer);
复制代码

上述代码

3、ObservableCreate.subscribeActual方法主要做了两件事,一是实例一个包装类CreateEmitter,用于包装我们传入的LambdaObserver对象,二是以我们之前定义ObservableOnSubscribe对象(ObservableCreate类的成员变量source对象)调用其subscribe方法,即触发我们定义的事件产生代码。

// ObservableCreate.java
protected void subscribeActual(Observersuper T> observer) {
    CreateEmitter parent = new CreateEmitter(observer);
    observer.onSubscribe(parent);

    try {
        source.subscribe(parent);
    } catch (Throwable ex) {
        Exceptions.throwIfFatal(ex);
        parent.onError(ex);
    }
}
复制代码
Observable.create {  // it::class.java = ObservableEmitter
    Log.d(TAG, "事件产生线程:${Thread.currentThread().name}")
    it.onNext("Hello world")
    it.onComplete()
}
复制代码

回到最开始我们的定义,这里的it被注释表明它是一个ObservableEmitter对象,即上述提到的在ObservableCreate.subscribeActual被实例的包装类CreateEmitter的父类,所以这里当我们调用譬如it.onNext时,就会触发CreateEmitter的onNext方法,以下是CreateEmitter.onNext方法:

// ObservableCreate.java
static final class CreateEmitter<T>
extends AtomicReference<Disposable>
implements ObservableEmitter<T>, Disposable {
...
    final Observersuper T> observer;

    CreateEmitter(Observersuper T> observer) {
        this.observer = observer;
    }

    public void onNext(T t) {
        if (t == null) {
            onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
            return;
        }
        if (!isDisposed()) {
            observer.onNext(t);
        }
    }
...
复制代码

结合上述ObservableCreate.subscribeActual方法可知, CreateEmitter类中的observer对象,是我们最开始的LambdaObserver对象,这里调用observer.onNext(t),实际上就是触发我们传入的onNext回调

上述源码:

至此,Observable.create的数据流就已经完成了闭环。

总结

基于上述的代码解析,笔者总结了一下关于RxJava的数据流套路:

  • 开发者使用API组装Rx的代码,其实质是多个集成自Observable的对象嵌套。而最后一个被嵌套的就是我们自己实现的用于事件产生的对象实现(source)(ps: 这里用于事件产生的对象并不统一,有像create是一个ObservableOnSubscribe对象,有像just是一个范型)
  • 当在外部调用subscribe时,会触发每个自定义Observable子类的用于处理订阅的抽象方法subscribeActual,其最终的效果就是 逐级调用subscribeActual方法,最终到达我们定义的事件产生那一级
  • 在subscribeActual方法中,一般会生成一个包装source(即上一级的嵌套对象)的装饰器对象,用于事件消费(onNext...)的触发。
  • 会在调用subscribeActual后,合适时机调用source的subscribe方法用于触发事件产生阶段
  • 2-3点描述了调用subscribe后的组装对象数据流,这个过程可以理解为 从subscribe自下而上的经过的操作符逐层嵌套
  • 事件产生后(譬如调用onNext后),数据流将会从事件产生那一级开始自上而下地通过譬如onNext方法传递

我们使用RxJava-Observable.create这个例子可以得出一个调用subscribe后的数据流流程图为: ps: 这里补充一点,订阅与事件产生并不是都像上述的例子在触发subscribe之后马上会有事件产生,大多情况是订阅与事件产生会是分开的。

RxSwift

Observable<String>.create

接下来的代码解析会基于以下代码进行:

Observable<String>.create { (ob) -> Disposable in
            print("事件产生线程:\(Thread.current.description)")
            ob.onNext("Hello world")
            ob.onCompleted()
            return Disposables.create()
        }
        .subscribe(onNext: { (str) in
            print("事件消费线程:\(Thread.current.description)")
            print(str)
        }, onError: nil, onCompleted: nil, onDisposed: nil)
复制代码

在解析之前,需要补充的是,在RxSwift中 调用onNext、onError等事件流,最终都会走到func on(_ event: Event)方法,所以源码中大多是通过实现on方法来实现事件流的传递回调。on方法的定义在ObserverType.swift

// ObserverType.swift
public protocol ObserverType {
    associatedtype Element

    (*, deprecated, renamed: "Element")
    typealias E = Element

    func on(_ event: Event)
}

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))
    }
}
复制代码

上述代码可知,Event为一个枚举类型,定义的是next、completed、error,对应的是onNext、onCompleted、onError。顺带一提,ObserverType为所有观察者的协议。

阶段1:创建/定义

// Create.swift
public static func create(_ subscribe: @escaping (AnyObserver) -> Disposable) -> Observable<Element> {
        return AnonymousObservable(subscribe)
    }
复制代码
// Create.swift
final private class AnonymousObservable<Element>: Producer<Element> {
    typealias SubscribeHandler = (AnyObserver<Element>) -> Disposable

    let _subscribeHandler: SubscribeHandler

    init(_ subscribeHandler: @escaping SubscribeHandler) {
        self._subscribeHandler = subscribeHandler
    }
...
}
复制代码
  • Observable.create方法中其实就是 创建一个AnonymousObservable对象,RxSwift里面的一个可订阅的对象。这里的create方法会让我们传入一个闭包。该闭包即用于事件产生
  • AnonymousObservable类中的成员变量就是create时传入的闭包,此闭包被起别名为SubscribeHandler,以便后续开发者调用触发subscribe时进行操作。

上述源码:

阶段2:订阅

1、当调用AnonymousObservable.subscribe后,会 先对我们传入onNext、onError等回调进行一次对象封装,这里会实例一个AnonymousObserver。最终会调用AnonymousObservable自身的subscribe重载方法。以下代码定义在AnonymousObservable的协议ObservableType的扩展方法。

// ObservableType+Extensions.swift
public func subscribe(onNext: ((Element) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil) -> Disposable {
            ...
            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
            )
    }
复制代码

AnonymousObserver有一个名为EventHandler的闭包, 其实现可见上述subscribe方法中,而该闭包的调用为该类的onCore方法,onCore方法的调用即为上述我们提到的ObserverType协议的on方法即为事件产生时。(ps: 这里的继承层级较多,建议对照源码查看。)

// AnonymousObserver.swift
final class AnonymousObserver<Element>: ObserverBase<Element> {
    typealias EventHandler = (Event<Element>) -> Void

    private let _eventHandler : EventHandler

    init(_ eventHandler: @escaping EventHandler) {
...
        self._eventHandler = eventHandler
    }

    override func onCore(_ event: Event) {
        return self._eventHandler(event)
    }
...
}
复制代码

上述源码:

2、从源码可知AnonymousObservable的代码中并没有subscribe方法的定义,这时我们需要往其 父类(Producer类) 寻找定义, 这里有一个CurrentThreadScheduler的线程调度,默认是当前线程运行,所以可以先不理会。从代码可知, 最终代码会调用自身的run方法,这里的run方法由AnonymousObservable实现。

// Producer.swift
class Producer<Element> : Observable<Element> {
    ...
    override func subscribe(_ observer: Observer) -> Disposable where Observer.Element == Element {
        if !CurrentThreadScheduler.isScheduleRequired {
           ...
            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
            }
        }
    }

    func run(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
        rxAbstractMethod()
    }
}
复制代码

上述源码:

3、AnonymousObservable.run方法:

一是 实例一个包装类AnonymousObservableSink,用于包装我们传入的AnonymousObserver对象

二是以 自身(AnonymousObservable)为参数调用AnonymousObservableSink.run方法。AnonymousObservableSink.run方法的实现其实就是调用AnonymousObservable的_subscribeHandler闭包对象,即触发我们定义的事件产生代码。

// Create.swift
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: 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)
    }
}
复制代码
// Create.swift
final private class AnonymousObservableSink<Observer: ObserverType>: Sink<Observer>, ObserverType {
    typealias Element = Observer.Element
    typealias Parent = AnonymousObservable<Element>
...

    func run(_ parent: Parent) -> Disposable {
     return parent._subscribeHandler(AnyObserver(self))
    }
...
复制代码
Observable<String>.create { (ob) -> Disposable in
            print("事件产生线程:\(Thread.current.description)")
            ob.onNext("I'm ")
            ob.onCompleted()
            return Disposables.create()
        }
复制代码

回到最开始我们的定义,这里的ob的类型为 AnonymousObservableSink.run中的AnyObserver对象,这里可以将其忽略理解为就是AnonymousObservableSink对象self,所以这里当我们调用譬如ob.onNext时,就会触发AnonymousObservableSink的onNext方法,最终其实会走到 AnonymousObservableSink.on方法

// Create.swift
final private class AnonymousObservableSink<Observer: ObserverType>: Sink<Observer>, ObserverType {
    ...
    override init(observer: Observer, cancel: Cancelable) {
        super.init(observer: observer, cancel: cancel)
    }

    func on(_ event: Event) {
        #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()
            }
        }
    }
...
复制代码

它的forwardOn方法在其父类 Sink中:

// Sink.swift
final func forwardOn(_ event: Event) {
        #if DEBUG
            self._synchronizationTracker.register(synchronizationErrorMessage: .default)
            defer { self._synchronizationTracker.unregister() }
        #endif
        if isFlagSet(self._disposed, 1) {
            return
        }
        self._observer.on(event)
    }
复制代码

最终我们可以看到, _observer对象其实就是AnonymousObserver对象,调用其on方法即可对应到onNext闭包的回调触发

上述源码:

至此,Observable.create的数据流就已经完成了闭环。

总结

  • 开发者使用API组装Rx的代码,其实质是 多个继承自ObservableType协议的对象嵌套。而最后一个被嵌套的就是我们自己实现的用于事件产生的对象实现(ps: 这里用于事件产生的对象并不统一,有像create是一个闭包,有像just是一个范型)。
  • 当在外部调用subscribe时,会触发 每个自定义ObservableType协议子类的用于处理订阅的抽象方法subscribe,其最终的效果就是 逐级调用subscribe方法,最终到达我们定义的事件产生那一级
  • 在subscribe方法中,一般会生成一个包装source(即上一级的嵌套对象)的 装饰器对象,用于事件消费(onNext...)的触发。 会在调用subscribe后,合适时机调用source的subscribe方法用于触发事件产生阶段。
  • 2-3点描述了调用subscribe后的组装对象数据流,这个过程可以理解为从subscribe 自下而上的经过的操作符逐层嵌套。
  • 事件产生后(譬如调用onNext后),数据流将会 从事件产生那一级开始自上而下地通过譬如onNext方法传递

我们使用RxSwift-Observable.create这个例子可以得出一个调用subscribe后的数据流流程图为: ps: 这里补充一点,订阅与事件产生并不是都像上述的例子在触发subscribe之后马上会有事件产生,大多情况是订阅与事件产生会是分开的。

最后

至此,RxJava和RxSwift两个版本的create数据流就分析完了,因为Rx的代码涉及的自定义类较多,非常容易出现混乱,笔者也是尽量通过标示重点和代码段辅助讲解。本文重点是通过create方法的数据流,归纳出Rx代码的一些封装套路,若阅读完感觉还是混乱建议自己通过代码结合本文梳理流程。下篇文章会重点结合上述总结的思路说说两个版本的subscribeOn与observeOn操作符实现。

系列文章:

文章分类
Android
文章标签