Rxjava2(二)、五種觀察者模式建立及背壓

EvanZch發表於2019-12-30

Android進階系列之第三方庫知識點整理。

知識點總結,整理也是學習的過程,如有錯誤,歡迎批評指出。

上一篇:Rxjava2(一)、基礎概念及使用

直接開整,上一篇基礎概念裡面說了,rxjava2 擴充套件於觀察者模式,我們上篇的只是簡單的介紹了用Observable來建立使用,其實rxjava2給我們提供了五種觀察者模式的建立方式。

1、Observable 和 Observer

能夠發射0或n個資料,並以成功或錯誤事件終止,在第一篇中已經舉例說明了,這裡就不再詳細說明。

2、Flowable 和 Subscriber

能夠發射0或n個資料,並以成功或錯誤事件終止。 支援背壓,可以控制資料來源發射的速度。

我們看到ObservableFlowable這兩個的區別就是後者支援背壓,那麼何為背壓?

2.1、什麼是背壓

背壓是一種現象,簡單來說就是在非同步操作中,上游傳送資料速度快於下游處理資料的速度,下游來不及處理,Buffer 溢位,導致事件阻塞,從而引起的各種問題,比如事件丟失,OOM等。

rxjava1中並不支援背壓,當出現事件阻塞時候,會直接丟擲 MissingBackpressureException 異常,但是在rxjava2中,提供了 Flowable 來建立被觀察者,通過Flowable 來處理背壓問題,我們可以簡單通過demo分析。

A:我們上游模擬迴圈傳送資料。

B:執行緒切換,非同步操作。

C:下游每隔一秒獲取資料。

我們Observable 建立,來模擬了背壓這個現象,我們在上游模擬無限迴圈的傳送資料,下游每次都休眠一秒再獲取資料,這樣肯定會造成我們前面提的問題,就是上游傳送太他丫的快了,下游根本處理不過來,我們先看結果。

看日誌,列印結果停留在了13就沒有繼續列印了?同時可以看到程式已經崩了,是因為在rxjava2中,Observable並不支援背壓操作,遇到背壓問題,它並不會報錯,也不會拋MissingBackpressureException 異常,但是記憶體會一直飆高,最後導致記憶體不足程式直接掛掉。

可以看到記憶體一直在往上飆,針對背壓這種現象,rxjava2中提出用 Flowable 來處理。

下面由淺入深,慢慢揭開Flowable 的神祕面紗。

我們先用Flowable建立一個基本的demo:

       Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                emitter.onNext("事件一");
                LogUtil.d(TAG + "--subscribe  傳送事件一");
                emitter.onNext("事件二");
                LogUtil.d(TAG + "--subscribe  傳送事件二");
                emitter.onNext("事件三");
                LogUtil.d(TAG + "--subscribe  傳送事件三");
                emitter.onNext("事件四");
                LogUtil.d(TAG + "--subscribe  傳送事件四");
                emitter.onComplete();
                LogUtil.d(TAG + "--subscribe  傳送完成");
            }
        }, BackpressureStrategy.ERROR) // 這裡需要傳入背壓策略,跟執行緒池裡面飽和策略類似,當快取區存滿時候採取的處理策略
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread()) // 執行緒切換,非同步操作
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        LogUtil.d(TAG + "--onSubscribe");
                        // 決定觀察者能接收多少個事件,多餘事件放入快取區
                        // Flowable 預設快取區大小為128,即最大能存放128個事件
                        s.request(3);
                    }

                    @Override
                    public void onNext(String s) {
                        LogUtil.d(TAG + "--onNext  接收到:" + s);
                    }

                    @Override
                    public void onError(Throwable t) {
                        LogUtil.d(TAG + "--onError  error=" + t.getLocalizedMessage());
                    }

                    @Override
                    public void onComplete() {
                        LogUtil.d(TAG + "--onComplete");
                    }
                });
複製程式碼

可以看到Flowable建立和Observable基本差不多,只是在create方法中多傳入BackpressureStrategy.ERROR 這麼一個背壓策略,這個後面會詳講。

onSubscribe 的回撥中,引數變成了Subscription,我們可以通過這個引數,讓觀察者自己設定要接收多少個事件,如果傳送的事件大於觀察者設定接收的事件,多餘事件將會存入Flowable快取區中。

Flowable快取區佇列大小隻能存放128個事件,如果超過,就會報異常。

結果:

傳送四個事件,觀察者通過Subscription.request(3)設定只接收三個事件,所以下游只接收三個,剩下一個放入Flowable快取區中。

如果我們觀察者不設定Subscription.request(x),即不接收事件,被觀察者仍然會傳送事件,並存入快取區中,觀察者可以動態呼叫Subscription.request(x)方法來獲取事件。

        Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {

                for (int x = 0; x <= 10; x++) {
                    LogUtil.d(TAG + "--subscribe  傳送了" + x + "個事件");
                    emitter.onNext(x + "事件");
                }
            }
        }, BackpressureStrategy.ERROR) 
                // 執行緒切換,非同步操作
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        LogUtil.d(TAG + "--onSubscribe");
                        subscription = s;
                        // s.request(3);  這裡不指定觀察者接收事件個數
                    }

                    @Override
                    public void onNext(String s) {
                        LogUtil.d(TAG + "--onNext  接收到:" + s);
                    }

                    @Override
                    public void onError(Throwable t) {
                        LogUtil.d(TAG + "--onError  error=" + t.getLocalizedMessage());
                    }

                    @Override
                    public void onComplete() {
                        LogUtil.d(TAG + "--onComplete");
                    }
                });
複製程式碼

動態獲取

findViewById(R.id.bt_get_event).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (subscription != null) {
                    LogUtil.d(TAG + "--onClick");
                    subscription.request(4);
                }
            }
        });
複製程式碼

可以看到我們觀察者一開始並沒有指定接收多少個事件,而是通過外接點選事件,來動態設定接收事件個數,我們看結果,當點選觸發後,我們收到了最先存入佇列的四個事件。

結果:

2.2、背壓策略

我們前面提到,Flowable 預設的快取區佇列大小為128,即只能存放上游傳送的128個事件,如果上游傳送的事件超過128,就需要我們指定相應的背壓策略來做不同的處理,BackpressureStrategy為我們提供了五種背壓策略。

整理如下:

策略 作用
MISSING 當快取區大小存滿(128),被觀察者仍然繼續傳送下一個事件時,丟擲異常MissingBackpressureException , 提示快取區滿了
ERROR 當快取區大小存滿(128)(預設快取區大小128),被觀察者仍然繼續傳送下一個事件時,直接丟擲異常MissingBackpressureException
BUFFER 當快取區大小存滿(128),被觀察者仍然繼續傳送下一個事件時,快取區大小設定無限大, 即被觀察者可無限傳送事件,但實際上是存放在快取區
DROP 當快取區大小存滿,被觀察者仍然繼續傳送下一個事件時, 超過快取區大小(128)的事件會被全部丟棄
LATEST 當快取區大小存滿,被觀察者仍然繼續傳送下一個事件時,只儲存最新/最後傳送的事件, 其他超過快取區大小(128)的事件會被全部丟棄

2.2.1、MISSING

當快取區大小存滿(128),被觀察者仍然繼續傳送下一個事件時,丟擲異常MissingBackpressureException , 提示快取區滿了

        Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                // 傳送129個事件,模擬超出快取區
                for (int x = 0; x < 129; x++) {
                    emitter.onNext(x + "事件");
                    LogUtil.d(TAG + "--subscribe  傳送了" + x + "個事件");
                }
            }
        }, BackpressureStrategy.MISSING) // 使用BackpressureStrategy.MISSING背壓策略
                // 執行緒切換,非同步操作
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        LogUtil.d(TAG + "--onSubscribe");
                        s.request(Integer.MAX_VALUE);
                    }

                    @Override
                    public void onNext(String s) {
                        LogUtil.d(TAG + "--onNext  接收到:" + s);
                    }

                    @Override
                    public void onError(Throwable t) {
                        LogUtil.d(TAG + "--onError  error=" + t);
                    }

                    @Override
                    public void onComplete() {
                        LogUtil.d(TAG + "--onComplete");
                    }
                });
複製程式碼

我們使用BackpressureStrategy.MISSING背壓策略,觀察者接收request(Integer.MAX_VALUE),此值也為推薦值。

結果:

我們看到,當傳送了128個事件後,再傳送第129個事件時候,拋了MissingBackpressureException異常,而且我們設定了觀察者接收也未接收到資料,說明是先存入快取區佇列,再傳送,當快取區中拋異常後,就停止了onNext()事件,我們可以驗證一下,當設定被觀察者傳送128事件。

        Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                // *******  傳送128個事件  ********
                for (int x = 0; x < 128; x++) {
                    emitter.onNext(x + "事件");
                    LogUtil.d(TAG + "--subscribe  傳送了" + x + "個事件");
                }
            }
        }, BackpressureStrategy.MISSING)
                // 執行緒切換,非同步操作
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        LogUtil.d(TAG + "--onSubscribe");
                        s.request(Integer.MAX_VALUE);
                    }

                    @Override
                    public void onNext(String s) {
                        LogUtil.d(TAG + "--onNext  接收到:" + s);
                    }

                    @Override
                    public void onError(Throwable t) {
                        LogUtil.d(TAG + "--onError  error=" + t);
                    }

                    @Override
                    public void onComplete() {
                        LogUtil.d(TAG + "--onComplete");
                    }
                });
複製程式碼

就是在上面demo的基礎上,改了傳送的事件個數,上游傳送128個事件,剛好為快取區大小,並不拋異常。

結果:

我們看到程式沒有拋異常,並且正常列印了快取區中的128個資料(從0開始),可以印證兩點

1、快取區大小確實為128

2、先存入快取區後再獲取(如果異常,onNext直接不呼叫)

2.2.2、ERROR

當快取區大小存滿(128)(預設快取區大小128),被觀察者仍然繼續傳送下一個事件時,直接丟擲異常MissingBackpressureException

        Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                // 傳送129個事件,模擬超出快取區
                for (int x = 0; x < 129; x++) {
                    emitter.onNext(x + "事件");
                    LogUtil.d(TAG + "--subscribe  傳送了" + x + "個事件");
                }
            }
        }, BackpressureStrategy.ERROR)
                // 執行緒切換,非同步操作
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        LogUtil.d(TAG + "--onSubscribe");
                        s.request(Integer.MAX_VALUE);
                    }

                    @Override
                    public void onNext(String s) {
                        LogUtil.d(TAG + "--onNext  接收到:" + s);
                    }

                    @Override
                    public void onError(Throwable t) {
                        LogUtil.d(TAG + "--onError  error=" + t);
                    }

                    @Override
                    public void onComplete() {
                        LogUtil.d(TAG + "--onComplete");
                    }
                });
複製程式碼

使用 BackpressureStrategy.ERROR 背壓策略

結果:

跟Missing一樣,直接拋了MissingBackpressureException異常且下游未接收到資料,同理,如果上游傳送資料小於等於128,正常傳送和接收。

2.2.3、BUFFER

當快取區大小存滿(128),被觀察者仍然繼續傳送下一個事件時,快取區大小設定無限大, 即被觀察者可無限傳送事件,但實際上是存放在快取區。

       Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                // 傳送129個事件,模擬超出快取區
                for (int x = 0; x < 129; x++) {
                    emitter.onNext(x + "事件");
                    LogUtil.d(TAG + "--subscribe  傳送了" + x + "個事件");
                }
            }
        }, BackpressureStrategy.BUFFER)
                // 執行緒切換,非同步操作
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        LogUtil.d(TAG + "--onSubscribe");
                        s.request(Integer.MAX_VALUE);
                    }

                    @Override
                    public void onNext(String s) {
                        LogUtil.d(TAG + "--onNext  接收到:" + s);
                    }

                    @Override
                    public void onError(Throwable t) {
                        LogUtil.d(TAG + "--onError  error=" + t);
                    }

                    @Override
                    public void onComplete() {
                        LogUtil.d(TAG + "--onComplete");
                    }
                });
複製程式碼

使用 BackpressureStrategy.BUFFER 背壓策略

更改快取區大小,不做限制。

結果:

可以看到,我們傳送的129個事件全部傳送且接收到了。

2.2.4、DROP

當快取區大小存滿,被觀察者仍然繼續傳送下一個事件時, 超過快取區大小(128)的事件會被全部丟棄

        Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                // 傳送129個事件,模擬超出快取區
                for (int x = 0; x < 129; x++) {
                    emitter.onNext(x + "事件");
                    LogUtil.d(TAG + "--subscribe  傳送了" + x + "個事件");
                }
            }
        }, BackpressureStrategy.DROP)
                // 執行緒切換,非同步操作
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        LogUtil.d(TAG + "--onSubscribe");
                        s.request(Integer.MAX_VALUE);
                    }

                    @Override
                    public void onNext(String s) {
                        LogUtil.d(TAG + "--onNext  接收到:" + s);
                    }

                    @Override
                    public void onError(Throwable t) {
                        LogUtil.d(TAG + "--onError  error=" + t);
                    }

                    @Override
                    public void onComplete() {
                        LogUtil.d(TAG + "--onComplete");
                    }
                });
複製程式碼

使用 BackpressureStrategy.DROP 背壓策略

丟掉大於快取區的事件。

結果:

結果很明瞭,並沒有拋異常同時也正常列印了,但是超過快取區的那個事件被拋棄,並沒有獲取到。

2.2.5、LATEST

當快取區大小存滿,被觀察者仍然繼續傳送下一個事件時,只儲存最新/最後傳送的事件, 其他超過快取區大小(128)的事件會被全部丟棄

        Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                // 傳送150個事件
                for (int x = 0; x < 150; x++) {
                    emitter.onNext(x + "事件");
                    LogUtil.d(TAG + "--subscribe  傳送了" + x + "個事件");
                }
            }
        }, BackpressureStrategy.LATEST)
                // 執行緒切換,非同步操作
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        LogUtil.d(TAG + "--onSubscribe");
                        s.request(Integer.MAX_VALUE);
                    }

                    @Override
                    public void onNext(String s) {
                        LogUtil.d(TAG + "--onNext  接收到:" + s);
                    }

                    @Override
                    public void onError(Throwable t) {
                        LogUtil.d(TAG + "--onError  error=" + t);
                    }

                    @Override
                    public void onComplete() {
                        LogUtil.d(TAG + "--onComplete");
                    }
                });
複製程式碼

使用 BackpressureStrategy.LATEST 背壓策略

傳送了150個事件

當超出128時,會儲存最新的一個事件,即會接收129個事件。

結果:

我們可以看到,觀察者端接收到129個資料,分別為快取區內資料,加上最新/最後一條資料,中間資料均被丟棄。

2.3、同步情況下`Flowable`

前面說過,背壓前提是非同步操作下,在同步下,我們並不會有背壓一說,因為在同一個執行緒,傳送資料後總是要等下游處理了才會傳送第二條資料,不會存在緩衝區,如下:

       Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                LogUtil.d(TAG + "--subscribe  傳送事件一");
                emitter.onNext("事件一");
                LogUtil.d(TAG + "--subscribe  傳送事件二");
                emitter.onNext("事件二");
                LogUtil.d(TAG + "--subscribe  傳送事件三");
                emitter.onNext("事件三");
                LogUtil.d(TAG + "--subscribe  傳送完成");
                emitter.onComplete();
            }
        }, BackpressureStrategy.ERROR).subscribe(new Subscriber<String>() {
            @Override
            public void onSubscribe(Subscription s) {
                LogUtil.d(TAG + "--onSubscribe");
                s.request(3);
            }

            @Override
            public void onNext(String s) {
                LogUtil.d(TAG + "--onNext  接收到:" + s);
            }

            @Override
            public void onError(Throwable t) {
                LogUtil.d(TAG + "--onError  error=" + t);
            }

            @Override
            public void onComplete() {
                LogUtil.d(TAG + "--onComplete");
            }
        });
複製程式碼

結果:

可以看到,事件都是順序執行,傳送一條接收一條,然後再執行下一條。

但是,我們可能會遇到這個一個情況,當上遊傳送了四條資料,但是下游只接收三條?我們改一下demo如下:

       Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                LogUtil.d(TAG + "--subscribe  傳送事件一");
                emitter.onNext("事件一");
                LogUtil.d(TAG + "--subscribe  傳送事件二");
                emitter.onNext("事件二");
                LogUtil.d(TAG + "--subscribe  傳送事件三");
                emitter.onNext("事件三");
                LogUtil.d(TAG + "--subscribe  傳送事件四");
                emitter.onNext("事件四");
                LogUtil.d(TAG + "--subscribe  傳送完成");
                emitter.onComplete();
            }
        }, BackpressureStrategy.ERROR).subscribe(new Subscriber<String>() {
            @Override
            public void onSubscribe(Subscription s) {
                LogUtil.d(TAG + "--onSubscribe");
                s.request(3);

            }

            @Override
            public void onNext(String s) {
                LogUtil.d(TAG + "--onNext  接收到:" + s);
            }

            @Override
            public void onError(Throwable t) {
                LogUtil.d(TAG + "--onError  error=" + t);
            }

            @Override
            public void onComplete() {
                LogUtil.d(TAG + "--onComplete");
            }
        });
複製程式碼

可以看到,被觀察者傳送了四個事件,但是觀察者只接收了三條。

結果:

可以看到,同樣拋了MissingBackpressureException異常

這裡可以使用BUFFER的背壓策略來處理,但是我們為了說明觀察者反向控制被觀察者,我們採用如下方案:

        Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                // 通過emitter.requested()獲取觀察者設定的接收的事件數目
                long requested = emitter.requested();
                LogUtil.d(TAG + "--subscribe 觀察者設定接收的事件數目:" + requested);

                for (int x = 0; x < requested; x++) {
                    LogUtil.d(TAG + "--subscribe  傳送事件" + x);
                    emitter.onNext("傳送事件" + x);
                }
                LogUtil.d(TAG + "--subscribe  傳送完成");
                emitter.onComplete();
            }
        }, BackpressureStrategy.BUFFER).subscribe(new Subscriber<String>() {
            @Override
            public void onSubscribe(Subscription s) {
                LogUtil.d(TAG + "--onSubscribe");
                // 設定觀察者接收事件數目為3
                s.request(3);

            }

            @Override
            public void onNext(String s) {
                LogUtil.d(TAG + "--onNext  接收到:" + s);
            }

            @Override
            public void onError(Throwable t) {
                LogUtil.e(TAG + "--onError  error=" + t);
            }

            @Override
            public void onComplete() {
                LogUtil.d(TAG + "--onComplete");
            }
        });
複製程式碼

我們在subscribe中通過emitter.requested()獲取觀察者中設定的接收事件數目,來動態的傳送資料,這樣就避免了上下游資料不同步問題。

結果:

2.4、使用操作符時背壓處理

我們前面都是通過create來建立Flowable,可以在Create第二個引數中傳入相應的背壓策略,Flowable所有的操作符都支援背壓,但是通過操作符建立的背壓策略預設為BackpressureStrategy.ERROR,我們可以通過

  • onBackpressureBuffer()
  • onBackpressureDrop()
  • onBackpressureLatest()

三種方式來指定相應的背壓策略。

        Flowable.interval(1, TimeUnit.MILLISECONDS)
                .observeOn(Schedulers.io())
                .subscribe(new Subscriber<Long>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        Log.d(TAG, "onSubscribe");
                        subscription = s;
                        s.request(Long.MAX_VALUE); //預設可以接收Long.MAX_VALUE個事件
                    }

                    @Override
                    public void onNext(Long aLong) {
                        LogUtil.i(TAG + "--onNext  aLong=" + aLong);
                        try {
                            // 延時一秒接收
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onError(Throwable t) {
                        LogUtil.e(TAG + "--onError  error=" + t);
                    }

                    @Override
                    public void onComplete() {
                        LogUtil.i(TAG + "--onComplete");
                    }
                });
複製程式碼

這裡我們通過 interval來建立Flowable,可以看到下游每一毫秒傳送一條資料,下游一秒處理一條,上游明顯快於下游,處理不過來資料放入快取池中,當快取池中佇列滿時,就會拋異常,因為其預設的背壓策略為BackpressureStrategy.ERROR

結果:

我們可以通過onBackpressureXXX其指定相應的背壓策略。

結果:

當我們指定背壓策略為BUFFER後,可以看到並沒有異常丟擲,程式一直在列印輸出。

3、Single和SingleObserver

只發射單個資料或錯誤事件。

        Single.create(new SingleOnSubscribe<String>() {
            @Override
            public void subscribe(SingleEmitter<String> emitter) throws Exception {
                // 只能傳送onSuccess或者onError,發射多條資料,只接受第一條
                emitter.onSuccess("Success");
                emitter.onError(new NullPointerException(""));
            }
        }).subscribe(new SingleObserver<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                LogUtil.d(TAG + "--onSubscribe");
            }

            @Override
            public void onSuccess(String s) {
                LogUtil.d(TAG + "--onSuccess  s=" + s);
            }

            @Override
            public void onError(Throwable e) {
                LogUtil.e(TAG + "--onError  error=" + e.getMessage());
            }
        });
複製程式碼

SingleEmitter發射器只能傳送一條onSuccess或者onError資料,如果發射器發射多條資料,觀察者只能接收到第一條資料。

結果:

4、Completable和CompletableObserver

不發射資料,只處理 onComplete 和 onError 事件。

方法onCompleteonError只可呼叫一個,同時呼叫,第一個生效。

5、Maybe和MaybeObserver

能夠發射0或者1個資料,要麼成功,要麼失敗。有點類似於Optional。

onSuccess方法一次訂閱只能傳送一次。

方法onCompleteonError只可呼叫一個,同時呼叫,第一個生效。

相關文章