RxJava2极速入门——Rxjava理念与基础知识

目录

RxJava入门理念

函数响应式编程的概念及特点

函数编程概念

函数编程特性

响应式编程概念

响应式编程的特性

RxJava的基础知识

RxJava的创建

RxJava的生命周期回调

RxJava的五种观察者模式

Observable与Observer

Flowable

Single与SingleObserver

Completable

Maybe

总结心得


RxJava入门理念

传统异步式编程解决繁琐的面对对象编程往往采用抽象的对象关系这种做法处理异步事件,往往在并发中处理异步式的事务必要实现不少的抽象对象用以具体解决这些异步式事务所期望的结果。导致了代码的维护效果过于冗重。

Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便地处理异数据流。RxJava充分体现函数响应式编程思维,解决编写传统的异步代码过于繁琐的痛点,采用函数式的方式使得代码更好维护以及编写。

函数响应式编程的概念及特点

函数响应式编程结合函数式及响应式优点用以解决传统的面向对象的抽象关系,响应式编程通过函数式编程的方式用以解决传统的Callback回调问题。

函数编程概念

面对越来越复杂的并发编程及分布式处理、多线程中常见的死锁、线程饥饿、竞争条件等问题,由于多线程并不像单线程那样单一而简单的定位程序BUG,往往看似毫无问题单线程编程任务在运行多线程中由于一些没有注意到的地方导致程序运行严重至奔溃线程无法调度严重堵塞等问题,其BUG也由于多种不可预料的条件而诞生往往难以复现及定位。

而函数式编程往往由于其数据不可变,因而没有其并发编程中问题,相对于并发编程它更较于安全,函数式编程可以将解决个问题的业务逻辑单独的看出是函数的求解,在其求解过程中,常常可运用于单一原则多次复用某一函数,同时并避免了状态以及变量的概念,思维更接近与数学运算。

函数编程特性

RxJava2极速入门——Rxjava理念与基础知识_第1张图片

响应式编程概念

响应式编程是一种面向数据流及变化传播的编程方式,意味着静态以及动态的数据流可以很直观被表达展示,而其相关的计算的数学模型会将变化的值直接以数据流的方式进行传播。

响应式编程的特性

RxJava2极速入门——Rxjava理念与基础知识_第2张图片

RxJava的基础知识

RxJava遵循Reactive Extensions原则基于JVM平台上的一种实现,通过使用观察着序列构建异步、基于事件的程序。基于观察者设计模式一种拓展,支持不同的数据、事件流以及额外的操作类,允许通过声明式方式构建不同的执行序列,使用抽象的方式去屏蔽底层中多线程、同步、线程安全、并发数据结构、非阻塞IO等逻辑实现,其次还支持Java1.5及之后版本,以及其基于JVM开发的各种语言。稍后的代码示例以Kotlin为主。

RxJava2极速入门——Rxjava理念与基础知识_第3张图片

RxJava的创建

RxJava的使用通常分为三部曲:

创建Observable(被观察者),它会决定什么时候触发事件以及触发怎么样的事件,也就是当你想程序执行到某一种条件的时候,你想处理的异步操作顺序以及操作次数都可以由它来决定。

创建Observer(观察者),它代表着不同的线程中执行异步处理事件业务逻辑回调都在里面去做操作,观察者在未执行的时候它永远待命的哨兵,举个例子:它就像一个阻击手,一直待命隐蔽藏在一个角落中,直到目标(被观察者)出现(程序所需要执行的异步条件的)阻击目标(执行你所期待的异步事件逻辑)。

使用subscribe()两者间进行订阅,这就好比阻击手有了,目标有了但是还得告诉阻击手你阻击的任务对象是谁你要在哪个地方去阻击他,这就是subscribe()方法实现所做的事情。

接下来看一下代码示例:

    /**
     * error or next
     * onComplete
     * */
    private fun createExample() {
        Observable
                .just("this is create Demo")
                .subscribe(
                        { logIMessage("createExample", "msg:$it") },
                        { logIMessage("createExample", "error:${it.message ?: "unkown Error"}") },
                        { logIMessage("createExample", "onComplete") }
                )
    }

    /**
     * subscribe
     * error or next
     * onComplete
     * */
    private fun createExample2() {
        Observable
                .just("this is create Demo")
                .subscribe(
                        { logIMessage("createExample2", "msg:$it") },
                        { logIMessage("createExample2", "error:${it.message ?: "unkown Error"}") },
                        { logIMessage("createExample2", "onComplete") },
                        { logIMessage("createExample2", "subscribe") }
                )
    }

 利用just()方法创建一个Observable类型的再通过subscribe()方法链式的将观察者绑定在一起。接下来我们追踪源码看看它做了啥。

    /**
     * @param item
     *            the item to emit
     * @param 
     *            the type of that item
     * @return an Observable that emits {@code value} as a single item and then completes
     * @see ReactiveX operators documentation: Just
     * @see #just(Object, Object)
     * @see #fromCallable(Callable)
     * @see #fromArray(Object...)
     * @see #fromIterable(Iterable)
     */
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public static  Observable just(T item) {
        ObjectHelper.requireNonNull(item, "The item is null");
        return RxJavaPlugins.onAssembly(new ObservableJust(item));
    }

    /**
     * Verifies if the object is not null and returns it or throws a NullPointerException
     * with the given message.
     * @param  the value type
     * @param object the object to verify
     * @param message the message to use with the NullPointerException
     * @return the object itself
     * @throws NullPointerException if object is null
     */
    public static  T requireNonNull(T object, String message) {
        if (object == null) {
            throw new NullPointerException(message);
        }
        return object;
    }

    /**
     * Calls the associated hook function.
     * @param  the value type
     * @param source the hook's input value
     * @return the value returned by the hook
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @NonNull
    public static  Observable onAssembly(@NonNull Observable source) {
        Function f = onObservableAssembly;
        if (f != null) {
            return apply(f, source);
        }
        return source;
    }

在源码中我们可以很清晰的看到T是一个泛型,通过使用内部封装的ObjectHelper去判断我们传入的泛型是否为空,用以避免我们创建这样一个Obserable被观察者,其次在利用RxJavaPlugins.onAssembly()这一个方法去将一个hook Function关联的一个被观察者创建出来,这里做了一个很有意思的事情,首先拿自身的一个Function用来判断是否是一个空的对象,如果不是调用自身的apply方法将其添加我们创建的被观察者然后返回给我们,如果为空就直接返回自身。为什么要通过使用apply呢?其实跟接下来的源码分析都有关系,通过使用apply讲他们的source相关的操作链接在一起,如果你实现了那些方法或者需要那些回调的时候通过判断回调去做你那些需要做的东西,当然如果你没有实现的话他做自己那默认的一套东西。

接下来我们以createExample2()方法中去查阅下subscribe中它究竟干了些啥?

    /**
     * Subscribes to an ObservableSource and provides callbacks to handle the items it emits and any error or
     * completion notification it issues.
     * 
*
Scheduler:
*
{@code subscribe} does not operate by default on a particular {@link Scheduler}.
*
* * @param onNext * the {@code Consumer} you have designed to accept emissions from the ObservableSource * @param onError * the {@code Consumer} you have designed to accept any error notification from the * ObservableSource * @param onComplete * the {@code Action} you have designed to accept a completion notification from the * ObservableSource * @param onSubscribe * the {@code Consumer} that receives the upstream's Disposable * @return a {@link Disposable} reference with which the caller can stop receiving items before * the ObservableSource has finished sending them * @throws NullPointerException * if {@code onNext} is null, or * if {@code onError} is null, or * if {@code onComplete} is null, or * if {@code onSubscribe} is null * @see ReactiveX operators documentation: Subscribe */ @CheckReturnValue @SchedulerSupport(SchedulerSupport.NONE) public final Disposable subscribe(Consumer onNext, Consumer onError, Action onComplete, Consumer 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; }

在源码注释中我们很容易清晰地知道onNext代表着在事件产生后正常执行的时候,也就是异步回调成功中所做一个事件分发,而onError则发生在异步回调错误中所做的一个事件分发,注意onNext和onError永远只有一个会被允许,也就是异步对应成功和失败所对应的关系一般,而onComple意思就是我已经做完想要的队列时间,不想再去接下接下来的要操作的事件所调用的方法,注意onComple一旦被调用意味着doOnNext也不会在被触发了。onComple与onError也是互斥的一对事件。onSubscribe那就很好理解了它执行在被观察者被订阅时所执行的一个函数。

RxJava的生命周期回调

RxJava也有自己执行的生命周期,在不同时期做不同事情这些可以在源码中很好的看到,以下以示例代码去看看这货在这些生命周期中究竟做了啥。

    private fun lifecyleExampleLog(message: String) = logIMessage("lifeCycleExample", message)

    /***/
    private fun lifeCycleExample() {
        Observable.just("this is lifeCycleExample")
                .doOnSubscribe {
                    //发生订阅后回调的的方法
                    lifecyleExampleLog("doOnSubscribe")
                }.doOnLifecycle(
                        //订阅后是否可以取消
                        { lifecyleExampleLog("doOnLifecycle is disposed${it.isDisposed}") },
                        { lifecyleExampleLog("doOnLifecycle is run") }
                )
                .doOnEach {
                    //Observable每次发送数据都会执行这个方法
                    lifecyleExampleLog("doOnEach:${when {
                        it.isOnNext -> "onNext"
                        it.isOnError -> "onError"
                        it.isOnComplete -> "onComplete"
                        else -> "nothing"
                    }}")
                }.doOnNext {
                    //在onNext前调用
                    lifecyleExampleLog("doOnNext:$it")
                }.doAfterNext {
                    //在onNext后调用
                    lifecyleExampleLog("doAfterNext:$it")
                }.doOnError {
                    //在onError前调用
                    lifecyleExampleLog("doOnError:${it.message ?: "unkown error message"}")
                }.doOnComplete {
                    //正常调用onComplete时被调用
                    lifecyleExampleLog("doOnComplete")
                }.doFinally {
                    //终止后调用不管是正常执行或者异常终止,优先于doAfterTerminate执行
                    lifecyleExampleLog("doFinally")
                }.doAfterTerminate {
                    //当onComplete或者onError执行后被触发
                    lifecyleExampleLog("doAfterTerminate")
                }.subscribe { lifecyleExampleLog("onNext value:$it") }
    }

 在我的示例代码以及注释中可以很清晰的得到相应的生命周期所得一些回调解析,重点来了我们来聊聊doAfterTerminal与doFinally它们的区别。

    /**
     * Registers an {@link Action} to be called when this ObservableSource invokes either
     * {@link Observer#onComplete onComplete} or {@link Observer#onError onError}.
     *
     * @param onFinally
     *            an {@link Action} to be invoked when the source ObservableSource finishes
     * @return an Observable that emits the same items as the source ObservableSource, then invokes the
     *         {@link Action}
     * @see ReactiveX operators documentation: Do
     * @see #doOnTerminate(Action)
     */
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final Observable doAfterTerminate(Action onFinally) {
        ObjectHelper.requireNonNull(onFinally, "onFinally is null");
        return doOnEach(Functions.emptyConsumer(), Functions.emptyConsumer(), Functions.EMPTY_ACTION, onFinally);
    }

    /**
     * Calls the specified action after this Observable signals onError or onCompleted or gets disposed by
     * the downstream.
     * @param onFinally the action called when this Observable terminates or gets disposed
     * @return the new Observable instance
     * @since 2.1
     */
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final Observable doFinally(Action onFinally) {
        ObjectHelper.requireNonNull(onFinally, "onFinally is null");
        return RxJavaPlugins.onAssembly(new ObservableDoFinally(this, onFinally));
    }

在源码注释中我们可以很容易的看到Finally其实就是在于当事件以及正常完成了或者因为错误甚至在双方取消订阅而去做的一些回调让开发者知道整个事件做到这里已经算是流程做完了但是最终流程要做一些结尾操作的业务逻辑就可以这里去做相应的东西了,而AfterTerminate是注册在事件流程真正算是完工了所去的一些相应的一些业务逻辑回调

RxJava的五种观察者模式

RxJava2极速入门——Rxjava理念与基础知识_第4张图片

Observable与Observer

其实在上一节生命周期我已经讲了它们间的一些破事了,接下来主要讲一下Observable的hot和cold区分了,讲到这里也许你会一脑懵比了啥?还有hot和cold什么鬼?

RxJava2极速入门——Rxjava理念与基础知识_第5张图片

 

嘿醒醒同学先别愤怒听小弟我慢慢道来:

当业务场景需要的时候,我们需要一个被观察者不管是不是被订阅了都要时刻发送最新的数据的处于一值发送状态的时候,例如我们自己根据Android5.0支持的NetWorkCallback这种网络状态监听回调时候结合Rxjava不管是不是订阅了都要发送当前网络变化的最新状态的场景。例如:

RxJava2极速入门——Rxjava理念与基础知识_第6张图片

诶诶收起的搬砖我还没说完呢?结合这样类似的场景我们就可以监听到某一时刻事件产生的时候我们可以多个地方同时针对当前最新事件去做适配和响应这就是Hot的作用了。你可以想象成一辆公交车,不管有没有乘客(观察者)在车上(产生订阅),公交车都要按照指定路线在运行(不管有没有订阅还是被观察者一直在搞事情),每一个公交车要停靠的车站(订阅的事件)【每停一次都会发送一次数据】这样的一个场景。

而cold呢只有在发生订阅了才会执行发送数据流。当有多个订阅者时候消息是一对一相对应的且接收顺序与订阅顺序是不一致的,但是它的消息队列是完整发送,说明他们各自事件也是互相独立的。

接下来我们看看示例代码

    private fun coldObservable() {
        /**
         * subscribe1与subscribe2结果不一致.两者独立,收发顺序不一致导致并发会存在问题
         * */
        val observable = Observable.create(ObservableOnSubscribe { emitter ->
            Observable.interval(10L, TimeUnit.MILLISECONDS, Schedulers.computation())
                    .take(Long.MAX_VALUE)
                    .subscribe {
                        if (it <= 10) emitter.onNext(it)
                        else emitter.onComplete()
                    }
        }).observeOn(Schedulers.newThread())
        observable.subscribe({ Log.i("coldObservable", "subscribe-1value:$it") })
        observable.subscribe { Log.i("coldObservable", "subscribe-2value:$it") }
    }


    private fun coldTobeHot() {
        val observable = Observable.create(ObservableOnSubscribe { emitter ->
            Observable.interval(10L, TimeUnit.MILLISECONDS, Schedulers.computation())
                    .take(Long.MAX_VALUE)
                    .subscribe {
                        if (it <= 10) emitter.onNext(it)
                        else emitter.onComplete()
                    }
        }).observeOn(Schedulers.newThread()).publish()
        observable.connect()
        observable.subscribe({ Log.i("coldObservable", "subscribe-1value:$it") })
        observable.subscribe { Log.i("coldObservable", "subscribe-2value:$it") }
    }

    private fun subjectTobeHot(){
        val observable = Observable.create(ObservableOnSubscribe { emitter ->
            Observable.interval(10L, TimeUnit.MILLISECONDS, Schedulers.computation())
                    .take(Long.MAX_VALUE)
                    .subscribe {
                        if (it <= 10) emitter.onNext(it)
                        else emitter.onComplete()
                    }
        }).observeOn(Schedulers.newThread())
        val subject = PublishSubject.create()
        observable.subscribe(subject)
        //使用toSerialized保证线程安全
        subject.toSerialized()
        subject.subscribe({ Log.i("coldObservable", "subscribe-1value:$it") })
        subject.subscribe { Log.i("coldObservable", "subscribe-2value:$it") }
    }

cold的写法和生命周期写法示例是没有什么区别,接下来的两种cold转hot写法就来详细说了,第一种写法使用publish这种操作符使得Observable转化为ConnectableObservable,而这一个对象就是hot一种实现的对象了。但是这仅仅只是将cold转换而已并没有真正去做hot不管有没有订阅去做发送数据的事情了。这时候还需要调用它的connect()方法告诉它开始要做hot发送数据事情。

而最后一种写法更好玩了,先利用PublishSubject.create()这一个方法创建一个PublishSubject对象担任被观察者这一对象,然后利用Subject继承Observable这一个方式去转发或者发送新的数据这样一个做法。所以Subject即使观察者也是被观察者有木有很无双啊?但是它存在线程不安全问题所以保证线程安全还是得调用toSerialized()这一个方法保证线程安全,这样来避免并发的问题。注意很多封装的RxBus没有使用线程安全这一做法会导致有并发缺陷。

当hot转cold的时候要使用RefCount这个修饰符,在官网上是这样解析的:“Make a connectable Observable behave like an ordinary Observable“。

RxJava2极速入门——Rxjava理念与基础知识_第7张图片

 

别急,我们来看看官网给出的解析流程图:

RxJava2极速入门——Rxjava理念与基础知识_第8张图片

在执行流程图中可以看到RefCount操作符把从一个可连接的Observable连接和断开的过程自动化了。它操作一个可连接的Observable,返回一个普通的Observable。当第一个订阅者/观察者订阅这个Observable时,RefCount连接到下层的可连接Observable。
RefCount跟踪有多少个观察者订阅它,直到最后一个观察者完成,才断开与下层可连接Observable的连接。如果所有的订阅者/观察者都取消订阅了,则数据流停止;如果重新订阅,则重新开始数据流。

写法如下:

private fun hotTobeCold() {
        val consumer1 = Consumer { logIMessage("hotTobeCold-consumer1", "value$it") }
        val consumer2 = Consumer { logIMessage("hotTobeCold-consumer2", "value$it") }
        val connectableObservable = Observable.create { emitter: ObservableEmitter ->
            Observable.interval(10, TimeUnit.MILLISECONDS, Schedulers.computation()).take(Integer.MAX_VALUE.toLong())
                    .subscribe {
                        emitter.onNext(it)
                    }
        }.observeOn(Schedulers.newThread()).publish()
        connectableObservable.connect()
        val observable = connectableObservable.refCount()
        var dispose1 = observable.subscribe(consumer1)
        var dispose2 = observable.subscribe(consumer2)
        Thread.sleep(50L)
        dispose1.dispose()
        dispose2.dispose()
        logIMessage("hotTobeCold", "resetDataSource")
        dispose1 = observable.subscribe(consumer1)
        dispose2 = observable.subscribe(consumer2)
        Thread.sleep(30L)
        dispose1.dispose()
        dispose2.dispose()
    }
/**
 * 运行效果如下:
 *
 * I/hotTobeCold-consumer1: value0
 * I/hotTobeCold-consumer2: value0
 * I/hotTobeCold-consumer1: value1
 * I/hotTobeCold-consumer2: value1
 * I/hotTobeCold-consumer1: value2
 * I/hotTobeCold-consumer2: value2
 * I/hotTobeCold-consumer1: value3
 * I/hotTobeCold-consumer2: value3
 * I/hotTobeCold: resetDataSource
 * I/hotTobeCold-consumer1: value0
 * I/hotTobeCold-consumer2: value0
 * I/hotTobeCold-consumer1: value1
 * I/hotTobeCold-consumer2: value1
 * 
 **/

在示例代码以及运行效果中验证得出:如果所有的订阅者/观察者都取消订阅了,则数据流停止;如果重新订阅,则重新开始数据流。

如果只是部分订阅被取消它会一直发送数据,而当发生新的订阅或者重新订阅的时候则会它会以当前最新数据进行发送示例代码和运行效果如下:

    private fun hotTobeCold2() {
        val consumer1 = Consumer { logIMessage("hotTobeCold2-consumer1", "value$it") }
        val consumer2 = Consumer { logIMessage("hotTobeCold2-consumer2", "value$it") }
        val consumer3 = Consumer { logIMessage("hotTobeCold2-consumer3", "value$it") }
        val connectableObservable = Observable.create { emitter: ObservableEmitter ->
            Observable.interval(10, TimeUnit.MILLISECONDS, Schedulers.computation()).take(Integer.MAX_VALUE.toLong())
                    .subscribe {
                        emitter.onNext(it)
                    }
        }.observeOn(Schedulers.newThread()).publish()
        connectableObservable.connect()
        val observable = connectableObservable.refCount()
        var dispose1 = observable.subscribe(consumer1)
        var dispose2 = observable.subscribe(consumer2)
        var dispose3 = observable.subscribe(consumer3)
        Thread.sleep(30L)
        dispose1.dispose()
        dispose2.dispose()
        logIMessage("hotTobeCold2", "consumer2 reset subscribe")
        dispose2 = observable.subscribe(consumer2)
        Thread.sleep(20L)
        dispose3.dispose()
        dispose2.dispose()
    }

/**
 * 运行效果:
 * I/hotTobeCold2-consumer1: value0
 * I/hotTobeCold2-consumer2: value0
 * I/hotTobeCold2-consumer3: value0
 * I/hotTobeCold2-consumer1: value1
 * I/hotTobeCold2-consumer2: value1
 * I/hotTobeCold2-consumer3: value1
 * I/hotTobeCold2-consumer1: value2
 * I/hotTobeCold2-consumer2: value2
 * I/hotTobeCold2-consumer3: value2
 * I/hotTobeCold2: consumer2 reset subscribe
 * I/hotTobeCold2-consumer3: value3
 * I/hotTobeCold2-consumer2: value3
 * I/hotTobeCold2-consumer3: value4
 * I/hotTobeCold2-consumer2: value4
 **/

对比于hotTobeCold(),hotTobeCold2()这一个方法新增了consume3在线程睡眠后将1、2取消订阅,仅仅留下3订阅,然后再将2订阅。运行结果中的出来验证得出只要订阅队列只要没有清空,它就会发送最新的数据,在cold转hot的时候,说过hot是按照顺序发送数据这里可以很好的第一次订阅顺序1-2-3然后取消就变为3之后重新订阅变为3-2所以接受数据打印顺序也是这样一个顺序。

Flowable

Flowable作用就是用来支持非阻塞性背压。Flowable的所有操作符默认支持背压并且可同时实现Recative Streams操作(Flowable原理以及源码分析会单独分离出来描述),Observable与Flowable区别:

  场景作用
Observable 处理小于等于1000条数据,几乎不出现OOM
处理不会背压的事件
处理同步流操作
   
Flowable 处理超过10K以上的元素
文件读写以及分析等
读取数据库数据
创建响应式接口
网络IO数据流

Single与SingleObserver

这种观察者模式与其余四种有很大的一个区别,在这种模式下仅仅支持onSuccess与onError这一事件。这一点就可以很轻易的在SingleObserver源码中看到了亦或是SingleEmiter,,例如SingleObserver的源码:

public interface SingleObserver {

    /**
     * Provides the SingleObserver with the means of cancelling (disposing) the
     * connection (channel) with the Single in both
     * synchronous (from within {@code onSubscribe(Disposable)} itself) and asynchronous manner.
     * @param d the Disposable instance whose {@link Disposable#dispose()} can
     * be called anytime to cancel the connection
     * @since 2.0
     */
    void onSubscribe(@NonNull Disposable d);

    /**
     * Notifies the SingleObserver with a single item and that the {@link Single} has finished sending
     * push-based notifications.
     * 

* The {@link Single} will not call this method if it calls {@link #onError}. * * @param t * the item emitted by the Single */ void onSuccess(@NonNull T t); /** * Notifies the SingleObserver that the {@link Single} has experienced an error condition. *

* If the {@link Single} calls this method, it will not thereafter call {@link #onSuccess}. * * @param e * the exception encountered by the Single */ void onError(@NonNull Throwable e); }

可以很清楚就能看到SingleObserv而其实就是一个接口,通过实现这个接口就能得到这种只专注于成功或者失败的观察者模式。例如下面的示例代码就可以很轻易的创建这种模式的观察者:

    private fun singleObserver() {
        /**
         *
         * 由于使用lambda表达式代码简化所以会在这里描述一些简化代码对应的代码块
         * create{} ==> SingleOnSubscribe{}
         *
         * */
        Single.create {
            //这里操作是否成功或者失败的发送
            it.onSuccess("success")
            it.onError(Throwable("this is a error"))
        }.subscribe({
            //成功的操作
            logIMessage("singleObserver", "success-value:$it")
        }, {
            //失败操作
            logIMessage("singleObserver", "error-value:${it.message?:""}")
        })
        //更加简洁实用方式 使用BiConsumer
        Single.create {
            it.onSuccess("success")
            it.onError(Throwable("this is a error"))
        }.subscribe({ t1, t2 ->
            logIMessage("singleObserver", "success-value:$t1")
            logIMessage("singleObserver", "error-value:${t2.message?:""}")
        })
    }

当然Single还可以支持使用toXXX等方法转换为其他观察者模式。

Completable

在这种模式下的是不会发送数据,为什么这样说呢?他只有一对互斥的onComple以及onError事件,以及它常常配合andThen修饰符在互斥事件某一个事件执行完后再去执行一个操作的作用,在CompletableEmitter的源码中是这样子:

public interface CompletableEmitter {

    /**
     * Signal the completion.
     */
    void onComplete();

    /**
     * Signal an exception.
     * @param t the exception, not null
     */
    void onError(@NonNull Throwable t);

    /**
     * Sets a Disposable on this emitter; any previous {@link Disposable}
     * or {@link Cancellable} will be disposed/cancelled.
     * @param d the disposable, null is allowed
     */
    void setDisposable(@Nullable Disposable d);

    /**
     * Sets a Cancellable on this emitter; any previous {@link Disposable}
     * or {@link Cancellable} will be disposed/cancelled.
     * @param c the cancellable resource, null is allowed
     */
    void setCancellable(@Nullable Cancellable c);

    /**
     * Returns true if the downstream disposed the sequence or the
     * emitter was terminated via {@link #onError(Throwable)},
     * {@link #onComplete} or a successful {@link #tryOnError(Throwable)}.
     * 

This method is thread-safe. * @return true if the downstream disposed the sequence or the emitter was terminated */ boolean isDisposed(); /** * Attempts to emit the specified {@code Throwable} error if the downstream * hasn't cancelled the sequence or is otherwise terminated, returning false * if the emission is not allowed to happen due to lifecycle restrictions. *

* Unlike {@link #onError(Throwable)}, the {@code RxJavaPlugins.onError} is not called * if the error could not be delivered. *

History: 2.1.1 - experimental * @param t the throwable error to signal if possible * @return true if successful, false if the downstream is not able to accept further * events * @since 2.2 */ boolean tryOnError(@NonNull Throwable t); }

类似于Single但是它比Single能做的事情也更加局限。创建使用的写法如下:

    private fun completableObserver(){
        Completable.create{
            try {
                TimeUnit.SECONDS.sleep(2)
                it.onComplete()
            } catch (e: Exception) {
                it.onError(e)
            }
        }.andThen(Observable.range(0,5))
                .subscribe { 
                    logIMessage("andThenAction","value:$it")
                }
    }

//源码andThen可转化为其他的Observer
    public final  Observable andThen(ObservableSource next) {
        ObjectHelper.requireNonNull(next, "next is null");
        return RxJavaPlugins.onAssembly(new CompletableAndThenObservable(this, next));
    }

    public final  Flowable andThen(Publisher next) {
        ObjectHelper.requireNonNull(next, "next is null");
        return RxJavaPlugins.onAssembly(new CompletableAndThenPublisher(this, next));
    }

    public final  Single andThen(SingleSource next) {
        ObjectHelper.requireNonNull(next, "next is null");
        return RxJavaPlugins.onAssembly(new SingleDelayWithCompletable(next, this));
    }

    public final  Maybe andThen(MaybeSource next) {
        ObjectHelper.requireNonNull(next, "next is null");
        return RxJavaPlugins.onAssembly(new MaybeDelayWithCompletable(next, this));
    }

    public final Completable andThen(CompletableSource next) {
        return concatWith(next);
    }

在示例代码中的源码andThen中可以的出当他执行完它的操作的时候可以使他转化为其他Observer当然它还可以像Single一样使用toXXX的方法转为对应Observer。

Maybe

Maybe是一种RxJava2中出现的一种新的类型,近似的将它理解为Single与Completable的结合。在其Emitter中的源码可以清晰看到它究竟做了些什么:

public interface MaybeEmitter {

    /**
     * Signal a success value.
     * @param t the value, not null
     */
    void onSuccess(@NonNull T t);

    /**
     * Signal an exception.
     * @param t the exception, not null
     */
    void onError(@NonNull Throwable t);

    /**
     * Signal the completion.
     */
    void onComplete();

    /**
     * Sets a Disposable on this emitter; any previous {@link Disposable}
     * or {@link Cancellable} will be disposed/cancelled.
     * @param d the disposable, null is allowed
     */
    void setDisposable(@Nullable Disposable d);

    /**
     * Sets a Cancellable on this emitter; any previous {@link Disposable}
     * or {@link Cancellable} will be disposed/cancelled.
     * @param c the cancellable resource, null is allowed
     */
    void setCancellable(@Nullable Cancellable c);

    /**
     * Returns true if the downstream disposed the sequence or the
     * emitter was terminated via {@link #onSuccess(Object)}, {@link #onError(Throwable)},
     * {@link #onComplete} or a
     * successful {@link #tryOnError(Throwable)}.
     * 

This method is thread-safe. * @return true if the downstream disposed the sequence or the emitter was terminated */ boolean isDisposed(); /** * Attempts to emit the specified {@code Throwable} error if the downstream * hasn't cancelled the sequence or is otherwise terminated, returning false * if the emission is not allowed to happen due to lifecycle restrictions. *

* Unlike {@link #onError(Throwable)}, the {@code RxJavaPlugins.onError} is not called * if the error could not be delivered. *

History: 2.1.1 - experimental * @param t the throwable error to signal if possible * @return true if successful, false if the downstream is not able to accept further * events * @since 2.2 */ boolean tryOnError(@NonNull Throwable t); }

有所区别的是Maybe只会发送发射0-1个数据,超过时则不会再发射数据。接下来看看示例代码

    private fun maybeObserver(){
        //仅仅会打印sucess1
        Maybe.create {
            emitter: MaybeEmitter ->
            emitter.onSuccess("sucess1")
            emitter.onSuccess("sucess2")
            emitter.onSuccess("sucess2")
        }.subscribe {
            logIMessage("MaybeExample1","value:$it")
        }
        //success事件不会发送的情况
        Maybe.create {
            it.onComplete()
            it.onSuccess("affter complete sucess")
        }.subscribe(
                {
                    logIMessage("MaybeExample2","value:$it")
                },
                {
                    logIMessage("MaybeExample2","value:${it.message?:"unknown error"}")
                },
                {
                    logIMessage("MaybeExample2","value:onComplete")
                }
        )
    }


/**
 * 运行效果:
 * I/MaybeExample1: value:sucess1
 * I/MaybeExample2: value:onComplete
 **/

从示例代码以及运行结果可以得出Maybe最多只会发射一次数据,以及数据没发射前也就是0次的时候说明了被onComple或者onError给抢夺了。这种场景就可以运用仅仅关心某个数据是否只需要关注一遍并且它的错误或者完成的时候的应该如何去进行相应的业务逻辑操作。

总结心得

RxJava是基于Rx准则实现的异步观察者模式的库,充分体现出响应式函数编程的风格以及思维,其五种不同类型的观察者模式搭配不同的场景可以适当的简化代码,但是有时会增添一些代码写法这些代码的写法可以更好的理解如何解决一些较于传统复杂的异步回调问题,其五种不同的观察者模式可以互相转化,hot、cold的使用特点应付与单对单、单对多的场景以及其事件是否独立或者共享按订阅顺序 分发,仅仅只有Flowable是支持背压的,背压后续会详细描述其牵涉的理念以及操作符以及线程操作过多,会在操作符以及线程操作描述完后专门描述。

最后附送上github地址后续代码也会在这个github上更新,点我传送

 

 

 

你可能感兴趣的:(RxJava2)