[譯] 大話(Observable 向 Observer 求婚)之我與 Rx Observable [Android RxJava2](這是什麼鬼)第七話

蝶翼的罪發表於2018-02-28

哇哦,又是新的一天,是時候學些新知識了。

大家好,希望你們都過得不錯。這是我們的 RxJava2 Android 系列第七篇文章了,[ part1part2part3part4part5part6part7part8]。這篇文章裡我們將繼續和 Rx 聊聊天。

動機:

動機和我在第一部分介紹給大家的一樣。

前言:

這篇文章沒什麼前言,因為這是上篇文章的續集呀。但是開始之前,我想我們還是要先複習一下上篇文章的內容。上篇文章中,Rx Observerable 告訴了我們冷熱 Observeable 的含義,隨後我向大家分享了一個相關概念的例子。再然後,我問到了 Subject。可是 Observable 覺得我們在瞭解 Subject API 之前要先熟悉 Observer API。所以我們這次從 Observer API 處繼續我們的對話。

續集:

我:是的,那你能否告訴我 Subject 的相關概念 和 他的不同例項,如 Publish、Behaviour 等。

Observable:呃...我覺得在瞭解這些之前,我得先和你聊聊 Observer 的 API 以及他們是如何工作的,並讓你知道如何使用 Lambda 或者函式式介面來替代一個完整的 Observer 介面。你覺得如何?

我:沒問題,我聽你的。

Observable:其實我們已經瞭解了 Observables。而且在之前的例子中,我們大量使用了多種 Observer。但我覺得在學習新的 API 之前我們還是應該先學習她(Observer)。我們等等她,五六分鐘就到了。

Observer:你好啊,Observable。最近怎麼樣?

Observable:多謝關心,還不錯。 Observer,他(即我)是我的新朋友。他正在學習我們,所以我希望你把你自己教給他。

Observer:沒問題,你(對我)好啊?

我:你好啊,我挺好的,謝謝。

Observer:在我開始介紹我自己之前,我有一個問題,你知道函式式介面嗎?

我:當然。 (註解:如果有人想複習一下這些概念,請參考 part3 )

Observer:很棒。所以你已經知道 Observable 是那個觀察資料流改變的角色了吧。如果有任何的改變,Observable 會通知他的觀察者(們)。因此 Observable 有很多型別,但是你要知道沒有我(Observer),他(Observable)什麼也不是 ? 。

Observable:哈哈哈,完全正確,親愛的(比心)。

Observer:任何地方只要你能看到 Observable,就百分百可以看到我。你可以認為我就是 Observable 和開發者們(比如我,等等)之間的橋樑。比如你是一個 Rx 的新手,你想要使用一些依賴 Rx 的第三方庫。你只有瞭解我,才能掌握那個庫。我覺得這個說法不為過。

我:?。

Observer:任何時候你想要知道 Observable 關心的那些資料產生了變化或者有什麼事件發生了,你需要使用我來訂閱那個 Observable。然後當 Observable 想要通知你那些變化時,他會通過我來轉告你。 所以你可以有很多種方式使用我 ,但是首先我會從我最基本的 API 講起。

我:額,我對你的那句“你可以有很多種方式使用我”有些困惑。

Observer:聽我說完,我相信最後就沒有困惑了。我最基本的 API 有四個方法,如下所示。

public interface Observer<T> {
    void onSubscribe(Disposable var1);

    void onNext(T var1);

    void onError(Throwable var1);

    void onComplete();
}
複製程式碼

這裡 T 是 Java 的泛型。我覺得不需要大篇幅討論 Java 的泛型。簡單地說泛型就是如果你在等待 Persion 型別的資料,那麼 T 就是 Persion 類。這裡不需要強制使用所有的四個基本 API,這完全取決於你的需求。我等會將會給你一些例子,你可以輕易的決定什麼時候使用這些基本的 API,什麼時候使用更簡化的 API。 現在我先一次介紹一個方法。

void onSubscribe(Disposable var1);:
複製程式碼

任何時候當你將 Observer 關聯上了 Observable,你將會獲得一個 Disposable 物件。他有著非常簡單的 API,如下所示。

public interface Disposable {
    void dispose();

    boolean isDisposed();
}
複製程式碼

呼叫 dispose() 意味著你不再關注 Observable 的變化。所以任何時候當我想要離開 Observable 時,我就會呼叫我的 Disposable var1;. var1.dispose() 方法。這也意味著我(Observer)和 Observable 分開了。在那之後任何發生在 Observable 上的事件我都不在關心,我也不會再更新或者傳達這個變化。我稍後會給你展示這個特性非常適合一些場景,尤其是在 Android 上。 第二個是 isDisposed(),這個方法僅在少數情況有用處,比如我想從 Observable 取得資料,但是我不知道我是否已經被脫離了,所以我可以用它來檢測是否我被脫離了。反之亦然,在我主動脫離之前,我不確定我是否已經脫離,我可以呼叫這個方法來檢測。如果我呼叫這個方法後結果是 false,那麼意味著我還沒有被脫離,從而我就可以呼叫 dispose() 方法。

void onNext(T var1);:
複製程式碼

當我訂閱 Observable 後,如果 Observable 想要通知我有變化或者新資料時,就會呼叫這個方法。 我覺得我需要解釋得更與眾不同一些。當 Observable 想要和我結婚時,他就會暴露他的 API subscribe(Observer) 給我,然後通過呼叫他的 subscribe() API 我接受了他的求婚,但是重要的是我也得到了 Disposable 物件,這意味著我可以在任何時候和 Observable 離婚。在我們結婚期間,Observable 會在他的資料或者事件流有任何變化時通知我。這個時候,Observable 就會呼叫我的 onNext([any data]) 方法。所以簡單的說當 Observable 的資料有任何變化時就會通過我的 onNext(T data) method 方法通知開發者(我)。

void onError(Throwable var1);:
複製程式碼

這個 API 對我來說更加關鍵和重要。任何時候當 Observable 發現了致命的問題,他就會使用我的 onError(Throwable var1) API 通知我。Throwable 會告訴我他的崩潰原因或者出現了什麼問題。 這也意味著任何時候 onError() 被呼叫後,Disposable.isDispose() 方法永遠會返回 true。所以即使我從不請求離婚,但是當 Observable 面臨一些問題後死去,我可以使用 isDispose() 並得到返回值 true 來發覺這個情況。

void onComplete();:
複製程式碼

這個 API 對我同樣的關鍵和重要。任何時候 Observable 準備好死亡或者與我脫離時,他會使用 onComplete() 來通知我。同樣 Observable 死亡或者與我脫離時,我的 Disposable 會與在 onError() API 中表現得一致。以上的概念希望我都講清了。

我:是的,我只有一個問題。onError 和 onComplete 的區別是什麼,因為在這兩個方法呼叫後 Observable 都不能再給我傳送任何資料的變化。

Observer:你可以認為 Observable 因 onError 而死就像人類因為一些疾病而死。比如 Observable 正在觀察伺服器的資料但是伺服器掛掉了,所以 Observable 是因為某個原因而死亡,而這個原因你將會從 onError 的 Throwable 物件中獲得。也許是 500 錯誤碼,伺服器沒有響應。反之 Observable 因 onComplete() 而死意味著伺服器向 Observable 傳送了一個完成的訊息,在那之後 Observable 不再適合承載更多的資料,因為他的職責是隻從伺服器獲取一次資料。所以在呼叫 onComplete() 後他將會自然死亡。這就是為什麼 Observer,也就是我不能獲取到死亡的原因,因為他是自然死亡的。有個值得關注的地方,當 onError 被呼叫後邏輯上 onComplete 是不能被 Observable 呼叫的,反之亦然。簡單地說 Observable 只能呼叫這兩個方法之一,onError 或 onComplete。Observable 決不允許同時呼叫 onError 和 onComplete。這下都清楚了嗎?

我:喔,清楚了。

Observer:現在我將會給你演示如何在實踐中使用我。這個例子中,我將會建立一個每秒都會給我資料的 Observable。我會用不同的方式使用這些資料和 Observable 來讓你清楚地明白我所有的 API。

private static Observable<Object> getObservable() {
    return Observable.create(observableEmitter -> {
        Observable.interval(1000, TimeUnit.MILLISECONDS)
                .subscribe(aLong -> observableEmitter.onNext(new Object()));
    });
}
複製程式碼

雖然這確實簡單的方法,但是可能還是會讓你感到困惑。當我與這個 Observable 結婚後,他會每秒給我一個資料。你看到 Observable 是這個方法的返回型別。因此任何時候我訂閱或者與這個 Observable 結婚我將會得到 Object 型別的資料。下面我將會忽略這些資料並只關注自己方法的呼叫。

Observer<Object> observer = new Observer<Object>() {
    @Override
    public void onSubscribe(Disposable disposable) {
        ObserverLecture.disposable = disposable;
    }

    @Override
    public void onNext(Object o) {
        System.out.println("onNext called");
    }

    @Override
    public void onError(Throwable throwable) {
        System.out.println("onError called. Die due to reason: "+throwable.getMessage());
    }

    @Override
    public void onComplete() {
        System.out.println("onComplete: Die with natural death");
    }
};
複製程式碼

是的,那就是我,彪悍的人生不需要解釋。每當我想要和這個 Observable 結婚或者訂閱他時,我會把我傳入 Observable.subscribe() 方法。

getObservable().subscribe(observer);
複製程式碼

這裡你看到了,我和這位 Observable 先生已經結婚了。?

完整的程式碼:

public class ObserverLecture {

    private static Disposable disposable;

    public static void main(String[] args) {

        Observer<Object> observer = new Observer<Object>() {

            @Override
            public void onSubscribe(Disposable disposable) {
                ObserverLecture.disposable = disposable;
            }
            @Override
            public void onNext(Object o) {
                System.out.println("onNext called");
            }
            @Override
            public void onError(Throwable throwable) {
                System.out.println("onError called. Die due to reason: "+throwable.getMessage());
            }
           @Override
            public void onComplete() {
                System.out.println("onComplete: Die with natural death");
            }
        };
        getObservable().subscribe(observer);
        while (true);
    }
    
    private static Observable<Object> getObservable() {
        return Observable.create(observableEmitter -> {
            Observable.interval(1000, TimeUnit.MILLISECONDS)
                    .subscribe(aLong -> observableEmitter.onNext(new Object()));
        });
    }
}
複製程式碼

如果我執行這片程式碼,我會持續地得到下面的輸出,也意味著這個程式永遠不會退出。

輸出: onNext called onNext called onNext called onNext called onNext called

現在我決定向你展示 Disposable,看看我們討論的是不是對的。我會先給你看看 isDisposable() 方法的使用,他會告訴我我是不是被離婚了。

/**
 * Created by waleed on 14/05/2017.
 */
public class ObserverLecture {

    private static Disposable disposable;

    public static void main(String[] args) throws InterruptedException {

        Observer<Object> observer = new Observer<Object>() {
            @Override
            public void onSubscribe(Disposable disposable) {
                ObserverLecture.disposable = disposable;
            }

            @Override
            public void onNext(Object o) {
                System.out.println("onNext called");
            }

            @Override
            public void onError(Throwable throwable) {
                System.out.println("onError called. Die due to reason: "+throwable.getMessage());
            }

            @Override
            public void onComplete() {
                System.out.println("onComplete: Die with natural death");
            }
        };

        getObservable().subscribe(observer);


        while (true){
            Thread.sleep(1000);
            System.out.println("disposable.isDisposed(): "+disposable.isDisposed());
        }

    }

    private static Observable<Object> getObservable() {
        return Observable.create(observableEmitter -> {
            Observable.interval(1000, TimeUnit.MILLISECONDS)
                    .subscribe(aLong -> observableEmitter.onNext(new Object()));
        });
    }
}
複製程式碼

這片程式碼和上面的很像,只有 while 迴圈這一處改變了。在 while 迴圈中,每一秒我都會列印 Disposable 的值來表明 Observer 是否被離婚了。 輸出: disposable.isDisposed(): false onNext called disposable.isDisposed(): false onNext called disposable.isDisposed(): false onNext called disposable.isDisposed(): false onNext called … infinite

所以你輕易地看到了 false,這意味著我沒有被離婚因為我從來沒有呼叫過 Disposable.dispose() 方法。現在是時候向你展示當我呼叫 dispose() 後會發生什麼了。

public class ObserverLecture {
    
    private static Disposable disposable;

    public static void main(String[] args) throws InterruptedException {

        Observer<Object> observer = new Observer<Object>() {
            @Override public void onSubscribe(Disposable disposable) {ObserverLecture.disposable = disposable;}
            @Override public void onNext(Object o) {System.out.println("onNext called");}
            @Override public void onError(Throwable throwable) {System.out.println("onError called. Die due to reason: " + throwable.getMessage());}
            @Override public void onComplete() {System.out.println("onComplete: Die with natural death");}
        };

        getObservable().subscribe(observer);
        
        int count = 0;
        while (true) {
            Thread.sleep(1000);
            System.out.println("disposable.isDisposed(): " + disposable.isDisposed());

            count++;
            if (count == 3)
                disposable.dispose();
        }

    }

    private static Observable<Object> getObservable() {
        return Observable.create(observableEmitter -> {
            Observable.interval(1000, TimeUnit.MILLISECONDS)
                    .subscribe(aLong -> {
                        observableEmitter.onNext(new Object());
                    });
        });
    }
}
複製程式碼

這裡的程式碼和上面的也只有在 while 迴圈處一個不同。這次我新增了一個 count 變數,所以在我從 Observable 獲得三次資料後我就會呼叫 dispose,從而讓我和 Observable 離婚了。 輸出: onNext called disposable.isDisposed(): false onNext called disposable.isDisposed(): false onNext called disposable.isDisposed(): false disposable.isDisposed(): true disposable.isDisposed(): true disposable.isDisposed(): true

現在你從輸出中能看到,三次後我得到了 true,這意味著我離婚了。問題 Observable 身上將會發生什麼,他會死去嗎?為了解決這個問題,我引入一個概念叫做 冷、熱 Observable。如果他是熱 Observable 那麼他不會死去。但如果他是冷的,他將會停止傳送資料。

現在我覺得沒有必要去討論 onNext() 了,因為我們已經在我們的例子中看到了這個方法會在 Observable 資料有任何改變的時候被呼叫。 所以是時候討論一下 onError() 和 onComplete() 了,同時包括疾病死亡和自然死亡。

public class ObserverLecture {

    private static Disposable disposable;

    public static void main(String[] args) throws InterruptedException {

        Observer<Object> observer = new Observer<Object>() {
            @Override public void onSubscribe(Disposable disposable) {ObserverLecture.disposable = disposable;}
            @Override public void onNext(Object o) {System.out.println("onNext called");
                                                    System.out.println("disposable.isDisposed(): " + disposable.isDisposed());}
            @Override public void onError(Throwable throwable) {System.out.println("onError called. Die due to reason: " + throwable.getMessage());}
            @Override public void onComplete() {System.out.println("onComplete: Die with natural death");}
        };
        getObservable().subscribe(observer);

        while (true) {
            Thread.sleep(1000);
            System.out.println("disposable.isDisposed(): " + disposable.isDisposed());
        }
    }

    private static Observable<Object> getObservable() {
        return Observable.create(observableEmitter -> {
            observableEmitter.onNext(new Object());
            observableEmitter.onNext(new Object());
            observableEmitter.onNext(new Object());
            observableEmitter.onNext(new Object());
            observableEmitter.onError(new RuntimeException("Die due to cancer"));
        });
    }
}
複製程式碼

這裡除了建立 Observable 的方法,我用的程式碼和上面幾乎一樣。這個 Observable 會傳送四次資料,然後會因為一些原因死去。這裡我顯示地創造了這個原因,這樣我們才好理解 onError() 的概念。 輸出: onNext called disposable.isDisposed(): false onNext called disposable.isDisposed(): false onNext called disposable.isDisposed(): false onNext called disposable.isDisposed(): false onError called. Die due to reason: Die due to cancer disposable.isDisposed(): true disposable.isDisposed(): true

這裡你也能輕鬆地看到,在我們的 Observable 死去時,他呼叫了我的 onError 方法。在他死後,我的 isDisposed() 總會返回 true。這說明我離婚了或成為了寡婦。

是時候看一下 onComplete() 了。

public class ObserverLecture {

    private static Disposable disposable;

    public static void main(String[] args) throws InterruptedException {

        Observer<Object> observer = new Observer<Object>() {
            @Override public void onSubscribe(Disposable disposable) {ObserverLecture.disposable = disposable;}
            @Override public void onNext(Object o) {System.out.println("onNext called"); System.out.println("disposable.isDisposed(): " + disposable.isDisposed());}
            @Override public void onError(Throwable throwable) {System.out.println("onError called. Die due to reason: " + throwable.getMessage());}
            @Override public void onComplete() {System.out.println("onComplete: Die with natural death");}
        };

        getObservable().subscribe(observer);

        while (true) {
            Thread.sleep(1000);
            System.out.println("disposable.isDisposed(): " + disposable.isDisposed());

        }

    }

    private static Observable<Object> getObservable() {
        return Observable.create(observableEmitter -> {
            observableEmitter.onNext(new Object());
            observableEmitter.onNext(new Object());
            observableEmitter.onNext(new Object());
            observableEmitter.onNext(new Object());
            observableEmitter.onComplete();
        });
    }
}
複製程式碼

你也看到了,我就改了一處地方。Observable 主動呼叫了 onComplete 方法。 輸出: onNext called disposable.isDisposed(): false onNext called disposable.isDisposed(): false onNext called disposable.isDisposed(): false onNext called disposable.isDisposed(): false onComplete: Die with natural death disposable.isDisposed(): true disposable.isDisposed(): true disposable.isDisposed(): true

我們很容易就看到,我在呼叫 Disposable.isDisposed() 時一直是 false,說明我還沒有離婚,我還可以從 Observable 獲得資料,但是當 onComplete() 呼叫後 isDispose() 永遠返回 true。這意味著因為 Observable 的自然死亡,我離婚了或者是變成了寡婦。

我:喔!謝謝你,Observer。你解釋地很棒,幫我解答了很多關於你的疑惑。但是我有些好奇為什麼有時候人們使用只有一個方法的 Consumer 來替代 Observer。這是什麼方法?

Observer:首先感謝你的誇獎。我可以向你解釋更多的 API,但是首先我覺得你應該在 Android 中使用上面的概念並給我一個示例,這樣對大家都有幫助。

我:我同意你的想法,但是我覺得當務之急先學習關於你的一切,然後我會給你一個 Android 中使用上述所有 API 的真實的例子。

Observer:好吧,如你所願。有時候需求並不複雜,儘管你可以使用 Observer 的四個方法但是我覺得使用這四個方法不是必須的,你完全可以用更少的程式碼來完成需求。因此我把我自己切分成了幾個函式式介面,你也可以認為這是對 Observer 的語法糖。例如:

public class ObserverLecture {

    public static void main(String[] args) {

        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {
                    
                    }

                    @Override
                    public void onNext(String string) {
                        System.out.println("onNext: "+string);

                    }

                    @Override
                    public void onError(Throwable throwable) {
                        System.out.println("onError");
                    }

                    @Override
                    public void onComplete() {
                        System.out.println("onComplete");
                    }
                });
    }
}
複製程式碼

輸出: onNext: A onNext: B onNext: C onNext: D onComplete

這裡你能看到我只關注資料,但是我不得不實現 onSubscribe、onError 和 onComplete 方法。看下個例子是如何使用更少的程式碼來達到相同的目的。

public class ObserverLecture {

    public static void main(String[] args) {

        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(s -> System.out.println(s));

    }
}
複製程式碼

上述這兩個例子在功能上是一模一樣的,但是這次你看的例子只用了兩行程式碼,而上面的那個程式碼則非常的長。所以我想和你分享我所有的函式式介面以及你如何在你的應用中使用它們。

public interface Consumer<T> {
    void accept(@NonNull T var1) throws Exception;
}
複製程式碼
public interface Action {
    void run() throws Exception;
}
複製程式碼

我有兩個函式式介面,一個最好使的 Consumer,還有一個是 Action。我們先聊一下 Consumer 介面。當我只關注資料且並不在乎任何其他狀態的變化時,比如我不想使用 Disposable 瞭解是否被分離,我也不想知道 Observable 是否死亡以及是否是自然死亡還是疾病死亡。在這種情況下,我就可以使用 Consumer API。因此我很感謝 Observable 提供這個選項讓我使用我的函式式介面來訂閱他。

Observable:?

Observer:是時候讓你看看我們使用的示例了。

public static void main(String[] args) {

    List<String> strings = Arrays.asList("A", "B", "C", "D");
    Observable.fromIterable(strings)
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    System.out.println(s);
                }
            });
}
複製程式碼

這裡我僅僅訂閱了 Observable 的 onNext() 回撥,你很容易就能看出來我生成了一個匿名內部類給 Observable 來訂閱。下面更神奇的來了,我有和你們說過我有函式式介面,這意味著我能生成一個 Lambda 表示式給 Observable 來訂閱而不再需要匿名內部類或者介面物件。

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(s -> System.out.println(s));
    }
}
複製程式碼

喔,你看到上面的例子了,就一行程式碼。

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(System.out::println);
    }
}
複製程式碼

喔,用了更少的程式碼量。這裡我使用了方法引用,但是上面的兩塊程式碼功能上是完全一致的。下面的例子還有個技巧。

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer);
    }

    private static Consumer<String > consumer = System.out::print;
    //private static Consumer<String > consumer2 = s->{};
}
複製程式碼

這裡我單獨定義了我的 Consumer 函式式介面,並使用這個物件來訂閱。 下面是如果我也想知道錯誤的資訊,我將如何被相同的函式式介面通知到。

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        System.out.println("Die due to "+throwable.getMessage());
                    }
                });
    }

    private static Consumer<String > consumer = System.out::print;
}
複製程式碼

這裡你可以看到 Observable 的 subscribe 方法的第二個引數是用來通知 onError 的。因此我也生成了一個相同的 Consumer 函式式介面,這個介面的泛型 T 是 Throwable 類。這麼用真的是超級簡答。 下面是我如何使用 Lambda 表示式獲得相同的內容。

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer,
                        throwable -> System.out.println("Die due to "+throwable.getMessage()));
    }

    private static Consumer<String > consumer = System.out::print;
}
複製程式碼

下面是我如何使用方法引用實現同樣的功能。

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer, System.out::print);
    }

    private static Consumer<String> consumer = System.out::print;
}
複製程式碼

喔,只有一件事要注意的是,這裡的方法引用僅僅是呼叫了 Throwable.toString(),並不能展現我們自定義的訊息。就像上面例子的那樣**(System.out.println(“Die due to “+throwable.getMessage())**。 現在是時候向你展示使用定義我自己的 Error Consumer API 並生成一個那樣的物件來訂閱。

public class ObserverLecture {
    
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer, error);
    }

    private static Consumer<String> consumer = System.out::print;
    private static Consumer<Throwable> error = System.out::print;
}
複製程式碼

我知道你現在一定很好奇如何知道 Observable 的 onComplete() 是否被呼叫。對於那種情況,我可以使用 Action 介面。我需要生成一個 Action 介面來作為 Observable 的 subscribe 的第三個引數,從而我能從 Action 介面的回撥了解到 Observable 是否完成。

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer, error, new Action() {
                    @Override
                    public void run() throws Exception {
                        System.out.println("OnComplete");
                    }
                });
    }

    private static Consumer<String> consumer = System.out::print;
    private static Consumer<Throwable> error = System.out::print;
}
複製程式碼

這兒你能看到我的 Action 匿名內部類作為訂閱的第三個介面。下面我要給你看下我們如何使用 Lambda 表示式和使用方法引用以及使用第一個單獨定義的物件替代它。

Lambda 表示式:

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer, error, 
                        () -> System.out.println("OnComplete"));
    }

    private static Consumer<String> consumer = System.out::print;
    private static Consumer<Throwable> error = System.out::print;
}
複製程式碼

方法引用:

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer, error, System.out::println);
    }

    private static Consumer<String> consumer = System.out::print;
    private static Consumer<Throwable> error = System.out::print;
}
複製程式碼

這兒我想提醒一件事,方法引用用在這裡只是幫助你理解概念,實際中沒什麼作用,因為只是向控制檯輸出了一個空行。

一個定義好的物件:

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer, error, complete);
    }

    private static Consumer<String> consumer = System.out::print;
    private static Consumer<Throwable> error = System.out::print;
    private static Action complete = ()-> System.out.println("onComplete");
}
複製程式碼

所以你也看到了,第三個引數其實是 Action 而不是Consumer。請牢記。

最後一個是 Disposable。當我想分離時,我如何獲得一個 Disposable 呢,這時我們可以用泛型 T 為 Disposable 的 Consumer 作為訂閱的第四個引數。

public class ObserverLecture {

    public static void main(String[] args) {
        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer, error, complete, new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        
                    }
                });
    }

    private static Consumer<String> consumer = System.out::print;
    private static Consumer<Throwable> error = System.out::print;
    private static Action complete = ()-> System.out.println("onComplete");
}
複製程式碼

到這兒我就能獲得 Disposable 了。看到這想必你也明白了,我既可以實現一個 Observer 也可以用函式式介面做到同樣的事。也就是說 Observer 訂閱等於 四個函式式介面訂閱的組合(Consumer, Consumer, Action, Consumer)。 好了,下面再給你看下我們如何使用 Lambda 表示式替代 Consumer。

public class ObserverLecture {

    private static Disposable d;

    public static void main(String[] args) {

        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer, error, complete, disposable -> d = disposable);
    }

    private static Consumer<String> consumer = System.out::print;
    private static Consumer<Throwable> error = System.out::print;
    private static Action complete = ()-> System.out.println("onComplete");
}
複製程式碼

作為一個獨立定義的物件:

public class ObserverLecture {

    private static Disposable d;

    public static void main(String[] args) {

        List<String> strings = Arrays.asList("A", "B", "C", "D");
        Observable.fromIterable(strings)
                .subscribe(consumer, error, complete, disposable);
        
    }
    
    private static Consumer<String> consumer = System.out::print;
    private static Consumer<Throwable> error = System.out::print;
    private static Action complete = ()-> System.out.println("onComplete");
    private static Consumer<Disposable> disposable = disposable -> d = disposable;
}
複製程式碼

希望我都把一切都講清楚了。最後我還想說下,用 Observer 介面或者使用函式式介面完全取決於開發者們自身的選擇。還有問題嗎?

Observable:等一下。我還想再次感謝一下 Observer,耽誤了她不少時間。我覺得你應該藉此給出一個更加合適的、實際中用到的、包含上面全部概念的例子,這應該幫助到讀者。

我:首先我也要先謝謝 Observer,你真棒!那 Observable,我等會給出一個 Android 中的例子吧,然後我就想學習 Observable 中的 Subject 了。

Observable:哈哈,好的。我就在這兒哪都不去,但是在那之前我們要先和 Observer 說再見了。

我:是的,謝謝 Observer 用你寶貴的時間給我們分享。其實我在日常程式設計任務中已經大量使用你了,但是直到現在我才知道為什麼我需要使用你以及你是如何工作的。再次感謝!

結語: 朋友們,大家好。希望上面的知識點都講清楚了,不過要在日常實踐中多多使用上面的知識點哦。現在我想應該和大家說再見了,週末愉快。 ?


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章