RxJava最簡單易懂最全面的總結(一)

學習RxJava之前必須先來看下Java的設置模式之一:觀察者模式(Observer Pattern)。

原因:RxJava的都是基於觀察者模式構建的。

關於觀察者模式論述總結:

意圖:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。

主要解決:一個對象狀態改變給其他對象通知的問題,而且要考慮到易用和低耦合,保證高度的協作。

何時使用:一個對象(目標對象,被觀察者)的狀態發生改變,所有的依賴對象(觀察者對象)都將得到通知,進行廣播通知。

如何解決:使用面向對象技術,可以將這種依賴關係弱化。

關鍵代碼:在抽象類裏有一個 ArrayList 存放觀察者們。

下面給出傳統觀察者模式代碼:

代碼目錄結構很簡單,被觀察者(Observable)和觀察者(Observer)各有一個接口和具體的(Concrete)實現類:

被觀察者接口:

package com.xw.observerpatterndemo.observable;

import com.xw.observerpatterndemo.observer.Observer;

public interface Observable {
    /**
     * 將觀察者註冊到被觀察者的List集合中
     * @param observer
     */
    public void registerObserver(Observer observer);

    /**
     * 將觀察者從被觀察者的List集合中刪除
     * @param observer
     */
    public void removeObserver(Observer observer);

    /**
     * 當被觀察者狀態發生改變時通知觀察者進行相應的更新(通過觀察者對象調用觀察者的update()方法)
     */
    public void notifyObservers();
}

被觀察者的具體實現類:

package com.xw.observerpatterndemo.observable;

import java.util.ArrayList;
import java.util.List;
import com.xw.observerpatterndemo.observer.Observer;

public class ConcreteObservable implements Observable {
    private List<Observer> mObservers;
    private int edition;
    private float cost;
    public ConcreteObservable() {
       mObservers = new ArrayList<>();
    }
    @Override
    public void registerObserver(Observer observer) {
        mObservers.add(observer);
    }
    @Override
    public void removeObserver(Observer observer) {
        int i = mObservers.indexOf(observer);
        if(i>=0){
            mObservers.remove(i);
        }
    }
    @Override
    public void notifyObservers() {
       for(int i=0 ; i < mObservers.size();i++){
           Observer observer = mObservers.get(i);
           observer.update(edition,cost);
       }
    }

    public void setInfomation(int edition,float cost){
        this.edition = edition;
        this.cost =cost;
        notifyObservers();
    }
}

觀察者(Observer)接口:

package com.xw.observerpatterndemo.observer;

public interface Observer {
    /**
     * 同步更新觀察者的狀態
     * @param edition
     * @param cost
     */
    public void update(int edition,float cost);
}

觀察者具體實現類(ConcreteObserver):

package com.xw.observerpatterndemo.observer;
import android.util.Log;

public class ConcreteObserver implements Observer {
    private int edition;
    private float cost;
    private String name;

    public ConcreteObserver(String name) {
        this.name = name;
    }
    
    @Override
    public void update(int edition, float cost) {
       this.edition = edition;
       this.cost = cost;
       buy();
    }

    private void buy() {
        Log.v("ConcreteObserver",name+"購買了"+edition+"期雜誌,花了"+cost+"元");
    }
}

下面是我用Android studio對上面的類的調用(你可以用eclipse),在MainActivity中:

package com.xw.observerpatterndemo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import com.xw.observerpatterndemo.observable.ConcreteObservable;
import com.xw.observerpatterndemo.observer.ConcreteObserver;

public class MainActivity2 extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        //創建被觀察者
        ConcreteObservable concreteObservable = new ConcreteObservable();
        //創建3個觀察者
        ConcreteObserver observerA = new ConcreteObserver("A");
        ConcreteObserver observerB = new ConcreteObserver("B");
        ConcreteObserver observerC = new ConcreteObserver("C");

        concreteObservable.registerObserver(observerA);
        concreteObservable.registerObserver(observerB);
        concreteObservable.registerObserver(observerC);
        //concreteObservable.removeObserver(observerA);

        concreteObservable.setInfomation(8,28);
    }
}

上面被觀察者代碼中,一旦它的數據狀態發生改變concreteObservable.setInfomation(8,28);上面定義的三個觀察者都會隨着它更新數據狀態,後臺輸出的結果:

2020-06-01  4267-4267/? V/ConcreteObserver: A購買了8期雜誌,花了28.0元
2020-06-01  4267-4267/? V/ConcreteObserver: B購買了8期雜誌,花了28.0元
2020-06-01  4267-4267/? V/ConcreteObserver: C購買了8期雜誌,花了28.0元

熟悉了觀察者模式之後再來看RxJava的定義和使用就比較順其自然了,RxJava的使用通常分爲三步:

(1) 創建Observable:

Observable 的字面意思是被觀察者,使用 Rxjava時需要創建一個被觀察者,它會決定什麼時候觸發事件以及觸發怎樣的事件。有點類似上游發送命令,可以在這裏決定異步操作模塊的序和異步操作模塊的次數。

(2) 創建 Observer:

Observe :即觀察者,它可以在不同的線程中執行任務。這種模式可以極大地簡化併發操作,因爲它創建了一個處於待命狀態的觀察者哨兵,可以在未來某個時刻響應被觀察者(Observable)的通知,而不需要阻塞等待Observable發射數據。

(3) 使用 subscribe()進行訂閱,即訂閱關係:

創建了Observable和 observer 之後,我們還需要使用 subscribe()方法將它們連接起來,這樣整個上下游就能銜接起來實現鏈式調用,產生訂閱關係。

上面的三步也進一步說明了RxJava的四要素:

① 被觀察者Observable;② 觀察者Observer; ③ 訂閱關係 subscribe() ;④ 事件;

用一句話概括四者的關係就是:Observable 和 Observer 通過 subscribe() 方法實現訂閱關係,從而 Observable 可以在需要的時候發出事件來通知 Observer。

按照上面的使用三部曲舉一個簡單的例子:

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;


public class MainActivity extends AppCompatActivity {
   private TextView textTips;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textTips = findViewById(R.id.text_tips);

        //第一步:創建被觀察者
        Observable observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("我愛我的故鄉!");
                emitter.onNext("那是我無數個夜晚醒來後魂牽夢縈的地方!");
                emitter.onNext("心與心雖遠隔千里!");
                emitter.onNext("但與故鄉確咫尺之間!");
                emitter.onComplete();
            }
        });

        //第二步:創建觀察者
        Observer observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String s) {
                Log.v("ssss",s);
                textTips.setText(s);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        };
        //第三步:產生訂閱關係:
        observable.subscribe(observer);
    }
}

運行程序,我還是在Android Studio中運行的,控制檯輸出結果如下:

2020-06-02  23617-23617/? V/ssss: 我愛我的故鄉!
2020-06-02  23617-23617/? V/ssss: 那是我無數個夜晚醒來後魂牽夢縈的地方!
2020-06-02  23617-23617/? V/ssss: 心與心雖遠隔千里!
2020-06-02  23617-23617/? V/ssss: 但與故鄉確咫尺之間!

被觀察者、觀察者、訂閱方法我們都直觀的創建和調用了,那麼什麼是RxJava中所說的事件呢?

上述的例子中,在“第二步:創建觀察者”的對象new Observer<String>() { ...}中,必須實現的四個方法onSubscribe(Disposable d) 、onNext(String s) 、 onError(Throwable e) 、onComplete(),後三者就是RxJava的三個事件:

來看一下它們在Observer接口中的源碼定義:

package io.reactivex;

import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;


public interface Observer<T> {

    /**
     * Provides the Observer with the means of cancelling (disposing) the
     * connection (channel) with the Observable in both
     * synchronous (from within {@link #onNext(Object)}) 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);

    /**
     * Provides the Observer with a new item to observe.
     * <p>
     * The {@link Observable} may call this method 0 or more times.
     * <p>
     * The {@code Observable} will not call this method again after it calls either {@link #onComplete} or
     * {@link #onError}.
     *
     * @param t
     *          the item emitted by the Observable
     */
    void onNext(@NonNull T t);

    /**
     * Notifies the Observer that the {@link Observable} has experienced an error condition.
     * <p>
     * If the {@link Observable} calls this method, it will not thereafter call {@link #onNext} or
     * {@link #onComplete}.
     *
     * @param e
     *          the exception encountered by the Observable
     */
    void onError(@NonNull Throwable e);

    /**
     * Notifies the Observer that the {@link Observable} has finished sending push-based notifications.
     * <p>
     * The {@link Observable} will not call this method if it calls {@link #onError}.
     */
    void onComplete();

}

下面簡單的解釋說明一下:

onNext() :普通事件,相當於 onClick() / onEvent(),所有的產生訂閱關係的Observer(觀察者)都能通過這個方法接收到傳遞過來的消息。

onCompleted(): 事件隊列完結。RxJava 不僅把每個事件單獨處理,還會把它們看做一個隊列。RxJava 規定,當不會再有新的 onNext() 發出時,需要觸發 onCompleted() 方法作爲結束標誌。

onError(): 事件隊列異常。在事件處理過程中出異常時,onError() 會被觸發,同時隊列自動終止,不允許再有事件發出。

在一個正確運行的事件序列中, onCompleted() 和 onError() 有且只有一個,並且是事件序列中的最後一個。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在隊列中調用了其中一個,就不應該再調用另一個,否則會報錯。

onSubscribe(Disposable d)裏面的Disposable對象要說一下,Disposable英文意思是可隨意使用的,用於管理訂閱關係的,如果需要取消訂閱則可以調用mDisposable.dispose()取消訂閱關係。

觀察者說完了,再來看一下被觀察者的創建方式,在Observable.java中:

    /**
     *......
     *......
     * @param <T> the element type
     * @param source the emitter that is called when an Observer subscribes to the returned {@code Observable}
     * @return the new Observable instance
     * @see ObservableOnSubscribe
     * @see ObservableEmitter
     * @see Cancellable
     */
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }

create(ObservableOnSubscribe<T> source)方法用於創建一個被觀察者,其中參數對象ObservableOnSubscribe<T> source 可以像上面的例子中那樣給定一個匿名對象,而這個類ObservableOnSubscribe<T>的源碼如下,它必須實現一個方法:

subscribe(@NonNull ObservableEmitter<T> emitter);

package io.reactivex;

import io.reactivex.annotations.*;

/**
 * A functional interface that has a {@code subscribe()} method that receives
 * an instance of an {@link ObservableEmitter} instance that allows pushing
 * events in a cancellation-safe manner.
 *
 * @param <T> the value type pushed
 */
public interface ObservableOnSubscribe<T> {

    /**
     * Called for each Observer that subscribes.
     * @param emitter the safe emitter instance, never null
     * @throws Exception on error
     */
    void subscribe(@NonNull ObservableEmitter<T> emitter) throws Exception;
}

這個subscribe(@NonNull ObservableEmitter<T> emitter)方法中傳遞了一個ObservableEmitter<T>類型的發射器參數emitter,點進這個類型我們會看到這個類的繼承關係: public interface ObservableEmitter<T> extends Emitter<T>{  },這個Emitter<T>是我們關心的,因爲它實現了幾個比較重要的方法,來看源碼:

/**
 * Copyright (c) 2016-present, RxJava Contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
 * the License for the specific language governing permissions and limitations under the License.
 */
package io.reactivex;

import io.reactivex.annotations.NonNull;

/**
 * Base interface for emitting signals in a push-fashion in various generator-like source
 * operators (create, generate).
 *
 * @param <T> the value type emitted
 */
public interface Emitter<T> {

    /**
     * Signal a normal value.
     * @param value the value to signal, not null
     */
    void onNext(@NonNull T value);

    /**
     * Signal a Throwable exception.
     * @param error the Throwable to signal, not null
     */
    void onError(@NonNull Throwable error);

    /**
     * Signal a completion.
     */
    void onComplete();
}

是不是很驚訝,原來被觀察者內部emitter.onNext()等方法是Emitter<T>接口定義的方法,而不是觀察者Observer接口中定義的方法,這裏是需要明確區分的,有的文章說在被觀察者中調用的onNext()、onError()、onComplete()方法是觀察者中定義的方法,應該是錯的。所以在這裏特別說一下。 

我們應該這樣理解,在被觀察者中發射器對象調用的onNext()、onError()、onComplete()發射信號的方法與觀察者中接收信號的方法是一一對應的,就OK了!

                emitter.onNext("我愛我的故鄉!");
                emitter.onNext("那是我無數個夜晚醒來後魂牽夢縈的地方!");
                emitter.onNext("心與心雖遠隔千里!");
                emitter.onNext("但與故鄉確咫尺之間!");
                emitter.onComplete();

最後給出上面例子的鏈式寫法:

package com.xw.rxjavademo;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;

public class MainActivity extends AppCompatActivity {

    private TextView textTips;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textTips = findViewById(R.id.text_tips);

        Observable.create(new ObservableOnSubscribe<String>() {

            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("我愛我的故鄉!");
                emitter.onNext("那是我無數個夜晚醒來後魂牽夢縈的地方!");
                emitter.onNext("心與心雖遠隔千里!");
                emitter.onNext("但與故鄉確咫尺之間!");
                emitter.onComplete();
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String s) {
                Log.v("ssss",s);
                textTips.setText(s);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
    }
}

或者使用Consumer<String>作爲信號的消費者!

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.functions.Consumer;

public class MainActivity extends AppCompatActivity {

    private TextView textTips;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textTips = findViewById(R.id.text_tips);

        Observable.create(new ObservableOnSubscribe<String>() {

            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("我愛我的故鄉!");
                emitter.onNext("那是我無數個夜晚醒來後魂牽夢縈的地方!");
                emitter.onNext("心與心雖遠隔千里!");
                emitter.onNext("但與故鄉確咫尺之間!");
                emitter.onComplete();
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.v("ssss",s);
                textTips.setText(s);
            }
        });
    }
}

Consumer接口的源碼定義很簡單,就一個需要重載的accept()方法:

package io.reactivex.functions;

/**
 * A functional interface (callback) that accepts a single value.
 * @param <T> the value type
 */
public interface Consumer<T> {
    /**
     * Consume the given value.
     * @param t the value
     * @throws Exception on error
     */
    void accept(T t) throws Exception;
}

輸出結果和上面一樣!

上面算是RxJava的入門使用基礎!後面我會總結一下RxJava常用的幾種操作符和線程控制Scheduler的內容。也方便以後查閱使用!

後面持續更新!目標1000篇文章原創和1000集視頻!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章