十七、RxJava篇(RxJava模式與原理)

一、前言

之前我們說 RxJava是基於起點到終點,之間通過一條線連接,這條線裏我們可以做相應的攔截操作的這種編程思維。其實在規範的稱呼中RxJava是基於觀察者設計模式的一種響應式編程思維。從RxJava兩個關鍵對象就可以看到Observable是我們的被觀察者、Observer是我們的觀察者。Observer通過觀察Observable的數據變換做出響應,然而又說RxJava使用的不是標準的觀察者設計模式。

二、觀察者設計模式

什麼是觀察者設計模式?
如下圖,我們有一個微信公衆號,公衆號可以定時更新文章並推送給關注的用戶。A和B用戶關注了公衆號,當公衆號更新文章的時候A和B收到了相應的推送。在這裏我們的公衆號就是一個被觀察者,A和B用戶就是觀察者。當公衆號更新消息推送的時候,A和B就可以通過觀察收到消息。


  • 通過代碼實現
    (1)創建被觀察者
package com.example.andoiddemo;

/**
 * 被觀察者接口
 */
public interface Observable {
    void addUser(Observer user);

    void removeUser(Observer user);

    void pushMessage(String msg);
}

package com.example.andoiddemo;


import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class WeChatObservable implements Observable {
    private static final String TAG ="WeChatObservable" ;
    private List<Observer> list = new ArrayList<>();
    @Override
    public void addUser(Observer user) {
        list.add(user);
    }
    @Override
    public void removeUser(Observer user) {
        list.remove(user);
    }

    @Override
    public void pushMessage(String msg) {
        Log.e(TAG, "觀察者推送了一條消息: "+msg );
        for (int i = 0; i <list.size() ; i++) {
            list.get(i).receiveMessage(msg);
        }
    }
}

(2)創建觀察者A和B

package com.example.andoiddemo;

/**
 * 觀察者
 */
public interface Observer {


    /**
     * 收到消息
     * @param msg
     */
    void receiveMessage(String msg);
}

package com.example.andoiddemo;

import android.util.Log;

public class AUserObserver implements Observer {
    private static final String TAG = "AUserObserver";

    @Override
    public void receiveMessage(String msg) {
        Log.e(TAG, "A用戶收到了消息: "+msg );
    }
}

package com.example.andoiddemo;

import android.util.Log;

public class BUserObserver implements Observer {
    private static final String TAG = "BUserObserver";

    @Override
    public void receiveMessage(String msg) {
        Log.e(TAG, "B用戶收到了消息: "+msg );
    }
}

(3)測試

    private void test7() {
        com.example.andoiddemo.Observer a = new com.example.andoiddemo.AUserObserver();
        com.example.andoiddemo.Observer b = new com.example.andoiddemo.BUserObserver();
        com.example.andoiddemo.Observable observable = new WeChatObservable();
        //添加關注
        observable.addUser(a);
        observable.addUser(b);
        observable.pushMessage("hello world");
        //移除關注
        observable.removeUser(b);
        observable.pushMessage("你好世界");
    }
2021-06-08 18:00:39.229 25088-25088/com.example.andoiddemo E/WeChatObservable: 觀察者推送了一條消息: hello world
2021-06-08 18:00:39.229 25088-25088/com.example.andoiddemo E/AUserObserver: A用戶收到了消息: hello world
2021-06-08 18:00:39.229 25088-25088/com.example.andoiddemo E/BUserObserver: B用戶收到了消息: hello world
2021-06-08 18:00:39.229 25088-25088/com.example.andoiddemo E/WeChatObservable: 觀察者推送了一條消息: 你好世界
2021-06-08 18:00:39.229 25088-25088/com.example.andoiddemo E/AUserObserver: A用戶收到了消息: 你好世界

通過以上的代碼我們發現,觀察者設計模式的核心就是被觀察者對象中有一個容器,這個容器包含了觀察者對象。當觀察者數據更新的時候,再通過容器中拿到被觀察者對象然後通知他們,這樣一來觀察者就收到了數據更新。再標準的觀察者設計模式中,這裏被觀察者只有一個,觀察者可以有多個。

三、觀察者設計模式與RxJava對比

以上我們知道在標準的觀察者設計模式中,被觀察者只有一個,而觀察者可以有多個。而我們再來看看RxJava的代碼。

  private void test8() {
        Observable.just("hello world").map(new Function<String, String>() {
            @Override
            public String apply(@NonNull String s) throws Exception {
                return s;
            }
        }).map(new Function<String, String>() {
            @Override
            public String apply(@NonNull String s) throws Exception {
                return s;
            }
        }).map(new Function<String, String>() {
            @Override
            public String apply(@NonNull String s) throws Exception {
                return s;
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onNext(@NonNull String s) {
                Log.e(TAG, "onNext: "+s );
            }

            @Override
            public void onError(@NonNull Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
    }

在test8的方法中我們看到Observable被觀察者通過just輸入一個事件,然後調用了3次map,每一次map操作都返回一個被觀察者,這樣就將事件依次變換傳遞給下面的被觀察者。而我們的觀察者要接收事件做出響應,必須要通過subscribe進行訂閱,並且觀察者響應的是最後一個被觀察者的事件。這裏就和標準的觀察者模式有所區別。

  • 標準的觀察者模式,被觀察者只有一個,觀察者可以有多個,當被觀察者發出事件的時候,所有添加的觀察者都能收到事件。
  • RxJava中的觀察者設計模式,被觀察者可以有多個,觀察者只有一個,兩者之間通過訂閱進行關聯。並且觀察者只接受最後一個被觀察者的事件。

四、RxJava事件發射以及map事件變換原理

1、事件發射

2、map事件變換

五、線程切換原理

1、subscribeOn(Schedulers.io())

講當前運行環境切換到Io線程,其實就子線程。原理就是將我們observer封裝成runnable對象,由線程池執行。


2、observeOn(AndroidSchedulers.mainThread())

將下面的代碼切換到主線程。原理就是ObservableObserveOn調用subscribe的時候本來應該是調用onNext 講事件往下發射,但是它是先通過Handler進行線程的切換


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