RxJava1 升級到 RxJava2 所踩過的坑

RxJava2

RxJava2 發(fā)布已經有一段時間了,是對 RxJava 的一次重大的升級郎逃,由于我的一個庫cv4j使用了 RxJava2 來嘗鮮前翎,但是 RxJava2 跟 RxJava1 是不能同時存在于一個項目中的,逼不得已我得把自己所有框架中使用 RxJava 的地方以及
App 中使用 RxJava 的地方都升級到最新版本。所以我整理并記錄了一些已經填好的坑专钉。

填坑記錄

1. RxJava1 跟 RxJava2 不能共存

如果,在同一個module中同時使用RxJava1和RxJava2累铅,類似如下:

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.7'
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.1.5'

那么跃须,很不幸你會遇到這樣的錯誤

Rxjava1和Rxjava2無法共存.jpeg

同理,在 App 中如果使用了 Rxjava2娃兽,但是某個第三方的 library 還在使用 Rxjava1 也會遇到同樣的錯誤菇民。

上面的錯誤是因為 RxAndroid 2.0.1 本身依賴了 RxJava 2.0.1。我們嘗試去掉對 RxJava 的依賴,只留下 RxAndroid 第练。還是會遇到問題阔馋。

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
//compile 'io.reactivex.rxjava2:rxjava:2.0.7'
compile 'io.reactivex:rxandroid:1.2.0'
//compile 'io.reactivex:rxjava:1.1.5'
去掉對Rxjava的依賴.jpeg

所以使用RxAndroid不能去掉對RxJava的依賴,我是這樣使用的娇掏。

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.7'

官方也是這樣解釋的

Because RxAndroid releases are few and far between, it is recommended you also
explicitly depend on RxJava's latest version for bug fixes and new features.

最后呕寝,我建議要升級到 RxJava2 的時候必須所有使用的地方都要升級,并且用最新的版本婴梧。

2. 新增Flowable

RxJava1 中 Observable 不能很好地支持 backpressure 下梢,會拋出MissingBackpressureException。所以在 RxJava2 中 Observable 不再支持 backpressure 塞蹭,而使用新增的 Flowable 來支持 backpressure 孽江。關于backpressure 的理解,可以看這篇文章番电。

Flowable的用法跟原先的Observable是一樣的竟坛。

3. ActionN 和 FuncN 改名

ActionN 和 FuncN 遵循Java 8的命名規(guī)則。
其中钧舌,Action0 改名成Action,Action1改名成Consumer涎跨,而Action2改名成了BiConsumer洼冻,而Action3 - Action9都不再使用了,ActionN變成了Consumer<Object[]>隅很。

同樣撞牢,Func改名成Function,Func2改名成BiFunction叔营,Func3 - Func9 改名成 Function3 - Function9屋彪,FuncN 由 Function<Object[], R> 取代。

4. Observable.OnSubscribe 變成 ObservableOnSubscribe

原先RxJava1的寫法:

        Observable.create(new Observable.OnSubscribe<String>() {
            
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("hello");
            }

        }).subscribe(new Action1<String>() {

            @Override
            public void call(String s) {
                System.out.println(s);
            }
        });

現在的寫法:

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

            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("hello");
            }

        }).subscribe(new Consumer<String>() {

            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });

5. ObservableOnSubscribe 中使用 ObservableEmitter 發(fā)送數據給 Observer

結合上一條绒尊,ObservableOnSubscribe 不再使用 Subscriber 而是用 ObservableEmitter 替代畜挥。

ObservableEmitter 可以理解為發(fā)射器,是用來發(fā)出事件的婴谱,它可以發(fā)出三種類型的事件蟹但,通過調用emitter的onNext(T value)、onComplete()和onError(Throwable error)可以分別發(fā)出next事件谭羔、complete事件和error事件华糖。 如果只關心next事件的話,只需單獨使用onNext()即可瘟裸。

需要特別注意客叉,emitter的onComplete()調用后,Consumer不再接收任何next事件。

6. Observable.Transformer 變成 ObservableTransformer

原先RxJava1的寫法:

    /**
     * 跟compose()配合使用,比如ObservableUtils.wrap(obj).compose(toMain())
     * @param <T>
     * @return
     */
    public static <T> Observable.Transformer<T, T> toMain() {
        return new Observable.Transformer<T, T>() {
           @Override
            public Observable<T> call(Observable<T> tObservable) {
                return tObservable
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

現在的寫法:

    /**
     * 跟compose()配合使用,比如ObservableUtils.wrap(obj).compose(toMain())
     * @param <T>
     * @return
     */
    public static <T> ObservableTransformer<T, T> toMain() {

        return new ObservableTransformer<T, T>() {

            @Override
            public ObservableSource<T> apply(Observable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

由于新增了Flowable兼搏,同理也增加了FlowableTransformer

    public static <T> FlowableTransformer<T, T> toMain() {

        return new FlowableTransformer<T, T>() {

            @Override
            public Publisher<T> apply(Flowable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

7. Subscription 改名為 Disposable

在 RxJava2 中卵慰,由于已經存在了 org.reactivestreams.subscription 這個類,為了避免名字沖突將原先的 rx.Subscription 改名為 io.reactivex.disposables.Disposable向族。

剛開始不知道呵燕,在升級 RxJava2 時發(fā)現 org.reactivestreams.subscription 這個類完全沒法做原先 rx.Subscription 的事情:(

順便說下,Disposable必須單次使用件相,用完就要銷毀再扭。

8. first() 用法改變

官方文檔是這么描述的first()的用法

1.x 2.x
first() RC3 renamed to firstElement and returns Maybe<T>
first(Func1) dropped, use filter(predicate).first()
firstOrDefault(T) renamed to first(T) and RC3 returns Single<T>
firstOrDefault(Func1, T) renamed to first(T) and RC3 returns Single<T>

以first(Func1)為例,first(Func1)后面還使用了push()夜矗,原先 Rxjava1會這樣寫

ConnectableObservable<Data> connectableObservable = Observable
          .concat(Observable.from(list))
          .first(new Func1<Data, Boolean>() {
                @Override
                public Boolean call(Data data) {
                    return DataUtils.isAvailable(data);
                }
            }).publish();

RxJava2 改成這樣

ConnectableObservable<Data> connectableObservable = Observable
          .concat(Observable.fromIterable(list))
          .filter(new Predicate<Data>() {

                @Override
                public boolean test(@NonNull Data data) throws Exception {
                    return DataUtils.isAvailable(data);
                }
            }).firstElement().toObservable().publish();

9. toBlocking().y 被 blockingY() 取代

在我的框架中存在著一個Optional類泛范,它跟Java 8的Optional作用差不多,原先是使用RxJava1來編寫的紊撕。

import rx.Observable;

/**
 * 使用方法:
 *      String s = null;
 *      Optional.ofNullable(s).orElse("default")); // 如果s為null,則顯示default,否則顯示s的值
 * @author Tony Shen
 *
 */
public class Optional<T> {

    Observable<T> obs;

    public Optional(Observable<T> obs) {
        this.obs = obs;
    }

    public static <T> Optional<T> of(T value) {
        if (value == null) {
            throw new NullPointerException();
        } else {
            return new Optional<T>(Observable.just(value));
        }
    }

    public static <T> Optional<T> ofNullable(T value) {
        if (value == null) {
            return new Optional<T>(Observable.<T>empty());
        } else {
            return new Optional<T>(Observable.just(value));
        }
    }

    public T get() {
        return obs.toBlocking().single();
    }

    public T orElse(T defaultValue) {
        return obs.defaultIfEmpty(defaultValue).toBlocking().single();
    }
}

升級到RxJava2之后罢荡,get() 和 orElse() 方法都會報錯,修改之后是這樣的对扶。

import io.reactivex.Observable;

/**
 * 使用方法:
 *      String s = null;
 *      Optional.ofNullable(s).orElse("default"); // 如果s為null,則顯示default,否則顯示s的值
 * @author Tony Shen
 *
 */
public class Optional<T> {

    Observable<T> obs;

    public Optional(Observable<T> obs) {
        this.obs = obs;
    }

    public static <T> Optional<T> of(T value) {
        if (value == null) {
            throw new NullPointerException();
        } else {
            return new Optional<T>(Observable.just(value));
        }
    }

    public static <T> Optional<T> ofNullable(T value) {
        if (value == null) {
            return new Optional<T>(Observable.<T>empty());
        } else {
            return new Optional<T>(Observable.just(value));
        }
    }

    public T get() {

        return obs.blockingSingle();
    }

    public T orElse(T defaultValue) {

        return obs.defaultIfEmpty(defaultValue).blockingSingle();
    }
}

10. PublishSubject

包括 PublishSubject 以及各種 Subject(ReplaySubject区赵、BehaviorSubject、AsyncSubject) 都不再支持backpressure浪南。

總結

RxJava2 所帶來的變化遠遠不止這些笼才,以后遇到的話還會繼續(xù)整理和總結,畢竟我使用的 RxJava2 還是很少的一部分內容络凿。

RxJava2 最好到文檔依然是官方文檔骡送。如果是新項目到話,可以毫不猶豫地使用RxJava2絮记,如果是在線上已經成熟穩(wěn)定的項目摔踱,可以再等等。對于新手的話怨愤,可以直接從 RxJava2 學起派敷,RxJava1 就直接略過吧。對于老手撰洗,RxJava2 還是使用原來的思想膀息,區(qū)別不大,從 RxJava1 遷移到 Rxjava2 也花不了多少工夫了赵。

BTW:本人的《RxJava 2.x 實戰(zhàn)》已在2018年出版潜支。

參考資料:

  1. https://github.com/ReactiveX/RxJava/wiki
  2. https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0
  3. http://www.dundunwen.com/article/275b1d92-f9da-4bb8-b111-3aa8a6ace245.html
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市柿汛,隨后出現的幾起案子冗酿,更是在濱河造成了極大的恐慌埠对,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裁替,死亡現場離奇詭異项玛,居然都是意外死亡,警方通過查閱死者的電腦和手機弱判,發(fā)現死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門襟沮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人昌腰,你說我怎么就攤上這事开伏。” “怎么了遭商?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵固灵,是天一觀的道長。 經常有香客問我劫流,道長巫玻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任祠汇,我火速辦了婚禮仍秤,結果婚禮上,老公的妹妹穿的比我還像新娘可很。我一直安慰自己诗力,他們只是感情好,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布根穷。 她就那樣靜靜地躺著,像睡著了一般导坟。 火紅的嫁衣襯著肌膚如雪屿良。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天惫周,我揣著相機與錄音尘惧,去河邊找鬼。 笑死递递,一個胖子當著我的面吹牛喷橙,可吹牛的內容都是我干的。 我是一名探鬼主播登舞,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼贰逾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了菠秒?” 一聲冷哼從身側響起疙剑,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后言缤,有當地人在樹林里發(fā)現了一具尸體嚼蚀,經...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年管挟,在試婚紗的時候發(fā)現自己被綠了轿曙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡僻孝,死狀恐怖导帝,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情皮璧,我是刑警寧澤舟扎,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站悴务,受9級特大地震影響睹限,放射性物質發(fā)生泄漏。R本人自食惡果不足惜讯檐,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一羡疗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧别洪,春花似錦叨恨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至痢毒,卻和暖如春送矩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哪替。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工栋荸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凭舶。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓晌块,卻偏偏與公主長得像,于是被迫代替她去往敵國和親帅霜。 傳聞我的和親對象是個殘疾皇子匆背,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內容

  • 前言 如果你對RxJava1.x還不是了解,可以參考下面文章身冀。 1. RxJava使用介紹 【視頻教程】2. Rx...
    jdsjlzx閱讀 21,181評論 3 78
  • 前言 通過本系列上一篇文章靠汁,我們了解了RxJava1中由于被觀察者發(fā)送事件的速度遠快于觀察者處理事件的速度導致的背...
    SherlockXu8013閱讀 1,851評論 6 12
  • 官方WIKI What's different in 2.0 RxJava2已經發(fā)布了兩周了蜂大,相比RxJava1,...
    今天是個大晴天閱讀 48,860評論 18 86
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,288評論 25 707
  • 今天沒有完成昨天的任務蝶怔,昨天晚上我就在想是我不想完成還是學不會奶浦,兩個原因都不是。目前接觸到的東西確實太簡單我肯定學...
    游爽a閱讀 882評論 0 0