RxJava2 操作符總結

Yuloran發表於2019-01-03

專案經驗,如需轉載,請註明作者:Yuloran (t.cn/EGU6c76)

前言

本文總結專案中常用的 Rxjava2 操作符。

CV大神

使用RxJava2原因

  • ★★★★★ 封裝了執行緒切換,不用自己封裝執行緒池、Handler了
  • ★★★★☆ 鏈式呼叫,一氣呵成

單值發射

Single:大多數場景都是單值發射,所以使用 Single 即可覆蓋大部分場景。

Case1. 在非UI執行緒執行且不關注結果

  • fromCallable
Single.fromCallable(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                Logger.d(TAG, "test: fromCallable() invoked on %s", Thread.currentThread().getName());
                return generateRandom();
            }
        }).subscribeOn(Schedulers.io()).subscribe();
複製程式碼

從名字 Callable 就能看出,這是個回撥函式,在 io 執行緒執行

  • defer
        Single.defer(new Callable<SingleSource<Integer>>() {
            @Override
            public SingleSource<Integer> call() throws Exception {
                Logger.d(TAG, "test: defer() invoked on %s", Thread.currentThread().getName());
                return Single.just(generateRandom());
            }
        }).subscribeOn(Schedulers.io()).subscribe();
複製程式碼

注意,不能直接使用 Single.just(generateRandom()).subscribeOn(Schedulers.io()).subscribe(),這麼寫將直接在當前執行緒呼叫 generateRandom() ,無法實現在 io 執行緒執行的效果。

Case2. 在非UI執行緒執行並關注結果

需要關注結果的場景,建議都訂閱 Consumer<Throwable>,因為 RxJava 內部捕獲了 Exception,導致外部無感知

        Single.fromCallable(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return generateRandom();
            }
        }).subscribeOn(Schedulers.io()).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                Logger.d(TAG, "test: accept(Integer integer) invoked on %s", Thread.currentThread().getName());
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                Logger.d(TAG, "test: accept(Throwable throwable) invoked on %s", Thread.currentThread().getName());
            }
        });
複製程式碼

Case3. 在非UI執行緒執行但在UI執行緒關注結果

        Single.fromCallable(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return generateRandom();
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                Logger.d(TAG, "test: accept(Integer integer) invoked on %s", Thread.currentThread().getName());
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                Logger.d(TAG, "test: accept(Integer integer) invoked on %s", Thread.currentThread().getName());
            }
        });
複製程式碼

Case4. 變換返回值

        Single.fromCallable(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return generateRandom();
            }
        }).map(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                return String.valueOf(integer + "_mapped");
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Logger.d(TAG, "test: " + s);
            }
        });
複製程式碼

Case5. 按順序做某事且下一件事依賴上一件事的結果[常用於網路請求介面依賴時]

        Single.defer(new Callable<SingleSource<String>>() {
            @Override
            public SingleSource<String> call() throws Exception {
                return getUserId();
            }
        }).flatMap(new Function<String, SingleSource<UserInfo>>() {
            @Override
            public SingleSource<UserInfo> apply(String userId) throws Exception {
                return getUserInfo(userId);
            }
        }).subscribeOn(Schedulers.io()).subscribe(new Consumer<UserInfo>() {
            @Override
            public void accept(UserInfo userInfo) throws Exception {
                Logger.d(TAG, "test: get userInfo success: " + userInfo);
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                Logger.e(TAG, "test: get userInfo error.", throwable);
            }
        });
複製程式碼

Case6. 併發讀取不同資料來源,轉換成同型別後,合併

        Single<IBook> novel = Single.fromCallable(new Callable<Novel>() {
            @Override
            public Novel call() throws Exception {
                return getNovel();
            }
        }).map(new Function<Novel, IBook>() {
            @Override
            public IBook apply(Novel novel) throws Exception {
                return new NovelAdapter(novel);
            }
        }).subscribeOn(Schedulers.io());

        Single<IBook> rxJava2Tutorial = Single.fromCallable(new Callable<RxJava2Tutorial>() {
            @Override
            public RxJava2Tutorial call() throws Exception {
                return getRxJava2Tutorial();
            }
        }).map(new Function<RxJava2Tutorial, IBook>() {
            @Override
            public IBook apply(RxJava2Tutorial rxJava2Tutorial) throws Exception {
                return new RxJava2TutorialAdapter(rxJava2Tutorial);
            }
        }).subscribeOn(Schedulers.io());

        Single.zip(novel, rxJava2Tutorial, new BiFunction<IBook, IBook, List<IBook>>() {
            @Override
            public List<IBook> apply(IBook iBook, IBook iBook2) throws Exception {
                List<IBook> books = new ArrayList<>(2);
                books.add(iBook);
                books.add(iBook2);
                return books;
            }
        }).subscribe(new Consumer<List<IBook>>() {
            @Override
            public void accept(List<IBook> iBooks) throws Exception {
                Logger.d(TAG, "test: books are " + iBooks);
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                Logger.d(TAG, "test: get books error.", throwable);
            }
        });
複製程式碼

多值發射

Observable:使用場景較少,比如搜尋功能需要不斷髮射搜尋關鍵字。

Case1. 搜尋頻率限制

        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(final ObservableEmitter<String> emitter) throws Exception {
                mEditText.addTextChangedListener(new TextWatcher() {
                    @Override
                    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                    }

                    @Override
                    public void onTextChanged(CharSequence s, int start, int before, int count) {
                    }

                    @Override
                    public void afterTextChanged(Editable s) {
                        if (!emitter.isDisposed()) {
                            emitter.onNext(s.toString().trim());
                        }
                    }
                });
            }
        }).debounce(200, TimeUnit.MILLISECONDS).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String keyword) throws Exception {
                        mTextView.setText(search(keyword));
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        Logger.e(TAG, "test: emitter keyword error.", throwable);
                    }
                });
複製程式碼

背壓

Flowable:使用場景最少,目前僅發射下載進度時可以用上。

Demo 地址

Click Here

總結

陳康肅公善射,當世無雙 ,公亦以此自矜。嘗射於家圃,有賣油翁釋擔而立,睨之久而不去。見其發矢十中八九,但微頷之。 康肅問曰:”汝亦知射乎?吾射不亦精乎?”翁曰:”無他, 但手熟爾。”康肅忿然曰:”爾安敢輕吾射!”翁曰:”以我酌油知之。”乃取一葫蘆置於地,以錢覆其口,徐以杓酌油瀝之,自錢孔入,而錢不溼。因曰:”我亦無他,惟手熟爾。”康肅笑而遣之。

RxJava2 原始碼解析及設計思想

相關文章