RxJava2.0 基本使用,和場景

RxJava接觸挺久了,但是在實際項目中大部分都是配合retrofit使網絡請求使用,其他需求比較少,就是想用的時候會忘記怎麼使用,所以這裏做個筆記,希望也能幫到他人

本文基於RxJava2.0

RxJava

自己覺得知道下面幾點就比較清楚了

  1. RxJava的異步實現,是通過一種擴展的觀察者模式來實現的
  2. RxJava 的觀察者模式:Observable (可觀察者,即被觀察者)、 Observer (觀察者)、 subscribe (訂閱)、事件。
  3. Observable 和 Observer 通過 subscribe() 方法實現訂閱關係,從而 Observable可以在需要的時候發出事件來通知 Observer
那麼既然是觀察者模式,那我們看下怎麼使用

創建被觀察者:使用基本的創建方式create()

Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                //通知觀察者
                e.onNext("通知觀察者");
                e.onComplete();
            }
        });

創建觀察者

Observer observer = new Observer<String>() {
           //RxJava 2.0 中新增的,傳遞參數爲Disposable ,Disposable 相當於RxJava1.x中的Subscription,用於解除訂閱。
            @Override
            public void onSubscribe(Disposable d) {
                //可用於取消訂閱
                d.dispose();
                //還可以判斷是否處於取消狀態
                //boolean b=d.isDisposed();
            }

            //觀察者接收到通知,進行相關操作
            @Override
            public void onNext(String o) {
                Log.d("","接收到觀察者發出的數據");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        };

訂閱,將被觀察者和觀察者關聯上

observable.subscribe(observer);

其他創建被觀察者的方式

just(T…): 將傳入的參數依次發送出去

Observable observable = Observable.just("Hello", "Hi", "Aloha");
// 將會依次調用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();

Observable.from… 拆分成具體對象後,依次發送出去

String[] words = {"Hello", "Hi", "Aloha"};
Observable observable = Observable.from(words);
// 將會依次調用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();

線程的切換–線程控制器的使用(Schedulers)

看下面的code 想大家看下注釋就會明白了

 Observable.just("a", "b", "c", "d")
                .subscribeOn(Schedulers.io())//指定數據發射在哪個線程執行
                .observeOn(Schedulers.newThread())//observeOn方法決定他下面的方法執行在哪個線程中
                .map(func1)//一個新線程中執行
                .observeOn(Schedulers.io())//observeOn方法決定他下面的方法執行在哪個線程中
                .map(func2)//io線程執行
                .observeOn(AndroidSchedulers.mainThread())////observeOn方法決定他下面的方法執行在哪個線程中
                .subscribe(consumer);//ui線程執行
Function<String, String> func1 = new Function<String, String>() {
        @Override
        public String apply(String s) throws Exception {
            return s + "===newThread===";
        }
    };

    Function<String, String> func2 = new Function<String, String>() {
        @Override
        public String apply(String s) throws Exception {
            return s + "===io===";
        }
    };

    Consumer<String> consumer = new Consumer<String>() {
        @Override
        public void accept(String o) throws Exception {
            Log.d("call", o.toString());
        }
    };

下面我們根據場景來進行使用

  • 場景一: 單請求異步處理(網絡請求)
  • 場景二: 多異步請求連續調用
  • 場景三: 進行數組、list的遍歷(耗時數據處理)
  • 場景四: 多異步請求合併處理
  • 場景五: 定時操作

    示例中會伴有Rxjava 的操作符出現,使用時會進行說明

場景一: 單請求異步處理(網絡請求)

由於在Android UI線程中不能做一些耗時操作,比如網絡請求,大文件保存等,所以在開發中經常會碰到異步處理的情況,我們最典型的使用場景是RxJava+Retrofit處理網絡請求

@GET("/user")
public Observable<User> getUser(@Query("userId") String userId);
getUser(userId)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<User>() {
        @Override
        public void onNext(User user) {
            userView.setUser(user);//使用得到的結果數據
        }

        @Override
        public void onCompleted() {
        }

        @Override
        public void onError(Throwable error) {
            // Error handling
            ...
        }
    });

場景er: 多異步請求連續調用

假如在得到User數據後,需要跟新本地的用戶數據,也是將新的額數據顯示到View上,兩步操作都是同時的,這個時候我們可以藉助”doOnNext “操作符

“doOnNext “操作符

doOnNext() 方法 是當onNext發生時纔會被調用
doOnNext()允許我們在每次輸出一個元素之前做一些額外的事情
注意:
在doOnNext()中不要去改變數據的值

processUser(user); // 嘗試修正 User 數據
userView.setUser(user);//顯示數據

代碼

getUser(userId)
    .doOnNext(new Consumer<User>() {
                    @Override
                    public void accept(User user) throws Exception {
                        processUser(user);//更改數據
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())//ui線程
                .subscribe(new Observer<User>() {
                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }

                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(User user) {
                        userView.setUser(user);//展示數據
                    }
                });

如果請求getUser()之前需要getToken接口返回的數據才能訪問

使用”flatmap”操作符
作用:將一個類型依據程序邏輯轉換成另一種類型

@GET("/token")
public Observable<String> getToken();

@GET("/user")
public Observable<User> getUser(@Query("token") String token, @Query("userId") String userId);
getToken()
    .flatMap(new Function<String, Observable<User>>() {
                    @Override
                    public Observable<User>> apply(String token) throws Exception {
                        return getUser(token, userId);//第二次網絡請求
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<User>() {


                    @Override
                    public void onSubscribe(Disposable disposable) {

                    }

                    @Override
                    public void onNext(User user) {
                        //獲取到的用戶數據
                    }

                    @Override
                    public void onError(Throwable throwable) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

場景三: 進行數組、list的遍歷(耗時數據處理)

使用”fromIterable”操作符 ,作用:遍歷發送列表的每個Item

ArrayList<String> arr1 = new ArrayList<>();
        arr1.add("url1");
        arr1.add("url2");
        arr1.add("url3");

        Observable.just(arr1)
                .subscribeOn(Schedulers.newThread())//指定數據發射在哪個線程執行
                .flatMap(new Function<List<String>, Observable<String>>() {
                    @Override
                    public Observable<String> apply(List<String> strings) throws Exception {
                        Log.d("flatMap Thread ::: ", Thread.currentThread().getName());
                        return Observable.fromIterable(strings);//遍歷列表發送
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())//切換到主線程
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.d("subscribe Thread ::: ", Thread.currentThread().getName());
                        Log.d("subscribe === ", s);
                    }
                });

場景四: 多異步請求合併處理

有時需要請求多個接口和,將多個接口請求回來的數據合併後使用,可以使用”zip”操作符
作用:組合多個Observable發射的數據集合,然後再發射這個組合結果Observable

 Observable.zip(getData1(), getData2(), new BiFunction<List<String>, List<String>, String>() {
            @Override
            public String apply(List<String> strings, List<String> strings2) throws Exception {

                return strings.get(0) + strings.get(0);//發送組合後的新數據
            }
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.d("接受新數據:::", s);
                    }
                });
 /**
     * 模擬請求數據1
     *
     * @return
     */
    private Observable<List<String>> getData1() {
        return Observable.create(new ObservableOnSubscribe<List<String>>() {
            @Override
            public void subscribe(ObservableEmitter<List<String>> e) throws Exception {
                ArrayList<String> contacters = new ArrayList<>();
                contacters.add("location:張三");
                contacters.add("location:李四");
                contacters.add("location:王五");
                e.onNext(contacters);
                e.onComplete();
            }
        });
    }

    /**
     * 模擬獲取數據2
     *
     * @return
     */
    private Observable<List<String>> getData2() {
        return Observable.create(new ObservableOnSubscribe<List<String>>() {
            @Override
            public void subscribe(ObservableEmitter<List<String>> e) throws Exception {
                ArrayList<String> contacters = new ArrayList<>();
                contacters.add("net:Zeus");
                contacters.add("net:Athena");
                contacters.add("net:Prometheus");
                e.onNext(contacters);
                e.onComplete();
            }
        });
    }

場景五: 定時操作

使用timer做定時操作。當有“x秒後執行y操作”類似的需求的時候,想到使用timer
* 例如:2秒後輸出日誌“hello world”,然後結束。

 //2秒後執行
        Observable.timer(2, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())//切換到主線程
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        tv_msg.setText("hello --- world");
                    }
                });

更多操作符使用,後續有時間再記錄

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