RxJava2與RxJava1的簡單對比

yangxi_001發表於2017-05-18

英文連結:What’s different in 2.0

RxJava2相比RxJava1,它的改動還是很大的:

Observable and Flowable

在前一個版本里backpressure被整合到了Observable中,官方也提供了很多方法讓我們來處理backpressure問題。但是有一些特殊的場景根本無法用其來解決,最常見的例如UI事件。而不處理backpressure有可能導致MissingBackpressureException的出現。

關於backpressure的概念可以看一下 
http://blog.csdn.net/jdsjlzx/article/details/52717636

為了解決這個問題,在RxJava2裡,引入了Flowable這個類:Observable不包含backpressure處理,而Flowable包含。

例如:

Flowable<Long> flowable = 
    Flowable.create((FlowableOnSubscribe<Long>) e -> {
        Observable.interval(10, TimeUnit.MILLISECONDS)
            .take(Integer.MAX_VALUE)
            .subscribe(e::onNext);
}, FlowableEmitter.BackpressureMode.DROP);


Observable<Long> observable = 
    Observable.create((ObservableOnSubscribe<Long>) e -> {
        Observable.interval(10, TimeUnit.MILLISECONDS)
            .take(Integer.MAX_VALUE)
            .subscribe(e::onNext);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

兩個物件都以10毫秒一次派發資料,假設訂閱他們的方法都是:

i -> {
    Thread.sleep(100);
    Log.e("lzx", "out : " + i);
}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

以100毫秒一次消費資料,消費資料的效率是生產的1/10。那麼

  • 對於observable 
    他會按照0,1,2,3,4…的順序依次消費,並輸出log,而沒有消費的資料將會都存在記憶體中。如果在RxJava1中,記憶體資料超過128個時將會丟擲MissingBackpressureException錯誤;而在RxJava2中並不會報錯,資料會一直放到記憶體中,直到發生OutOfMemoryError。

  • 對於flowable, 在建立時我們設定了FlowableEmitter.BackpressureMode.DROP,一開始他會輸出0,1,2,3….127但之後會忽然跳躍到966,967,968 …。中間的部分資料由於快取不了,被拋棄掉了。

Single

和Observable,Flowable一樣會傳送資料,不同的是訂閱後只能接受到一次:

Single<Long> single = Single.just(1l);

single.subscribe(new SingleObserver<Long>() {
    @Override
    public void onSubscribe(Disposable d) {
    }

    @Override
    public void onSuccess(Long value) {
        // 和onNext是一樣的
    }

    @Override
    public void onError(Throwable e) {
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

普通Observable可以使用toSingle轉換:Observable.just(1).toSingle()。

Completable

與Single類似,只能接受到完成(onComplete)和錯誤(onError)

同樣也可以由普通的Observable轉換而來:Observable.just(1).toCompletable()

可訂閱的物件在RxJava1中只有Observable一種,之前我們經常會直接把資料來源稱作Observable。而在RxJava2中擴充成了4種,因此在之後還是把他們統稱為資料來源為宜。

Base reactive interfaces

和Flowable的介面Publisher類似,Observable、Single、Completable也有類似的基類。

interface ObservableSource<T> {
    void subscribe(Observer<? super T> observer);
}

interface SingleSource<T> {
    void subscribe(SingleObserver<? super T> observer);
}

interface CompletableSource {
    void subscribe(CompletableObserver observer);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

因此許多操作符接受的引數從以前的具體物件,變成了現在的介面:

Flowable<R> flatMap(
    Function<? super T, ? extends Publisher<? extends R>> mapper
);

Observable<R> flatMap(
    Function<? super T, ? extends ObservableSource<? extends R>> mapper
);

------
// 以前
Observable<R> flatMap(Func1<? super T, ? extends Observable<? extends R>> func) {
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

由於接收的都是介面,在使用其他遵循Reactive-Streams設計的第三方庫的時候,就不需要把他自定義的Flowable轉換成標準Flowable了。

Subjects and Processors

io.reactivex.subjects.AsyncSubject,
io.reactivex.subjects.BehaviorSubject,
io.reactivex.subjects.PublishSubject,
io.reactivex.subjects.ReplaySubject,
io.reactivex.subjects.UnicastSubject
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

在RxJava2中依然存在,但現在他們不支援backpressure。新出現的

io.reactivex.processors.AsyncProcessor,
io.reactivex.processors.BehaviorProcessor,
io.reactivex.processors.PublishProcessor,
io.reactivex.processors.ReplayProcessor
io.reactivex.processors.UnicastProcessor
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

支援backpressure

Other classes

rx.observables.ConnectableObservable變成了io.reactivex.observables.ConnectableObservable< T>和io.reactivex.flowables.ConnectableFlowable< T>

類似的還有rx.observables.GroupedObservable。

Functional interfaces

需要注意的一點是,現在RxJava2的介面方法里加上了throws Exception:

public interface Consumer<T> {
    void accept(T t) throws Exception;
}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

意味著在這些方法裡呼叫一些會發生異常的方法不需要try-catch了。

Actions

另外大部分介面方法都按照Java8的介面方法名進行了相應的修改,比如上面那個Consumer< T>介面原來叫Action1< T>,而Action2< T>改名成了BiConsumer。

Action3-Action9被刪掉了,大概因為沒人用。

Functions

同上,基本就是名字的修改和不常用類的刪除。

Subscriber

RxJava1裡Subscriber只是一個空介面,在新版裡Subscriber被賦予了更多的作用,有幾個實現類可以供我們使用,例如

ResourceSubscriber<Integer> subscriber = new ResourceSubscriber<Integer>() {
    @Override
    public void onStart() {
        request(Long.MAX_VALUE);
    }

    @Override
    public void onNext(Integer t) {
        System.out.println(t);
    }

    @Override
    public void onError(Throwable t) {
        t.printStackTrace();
    }

    @Override
    public void onComplete() {
        System.out.println("Done");
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

request()方法可以控制當前subscriber需要接收幾個事件。而且,還可以呼叫subscriber.dispose()來斷開對訊號的監聽。

同時,onCompleted方法改成了onComplete。意味著完成時呼叫這個方法,而不是完成後d

由於Subscription被改掉了(下面會講到)。如果需要類似以前CompositeSubscription的用法,可以使用:

CompositeDisposable composite2 = new CompositeDisposable();
  • 1
  • 1

注意這裡需要使用subscribeWith而不是subscribe,因為subscribe方法現在返回void。

Subscription

在RxJava1裡,Subscription起到的是訂閱橋樑的作用。在RxJava2中,由於Subscription本身和Reactive-Streams裡的另外一個同名概念衝突。因此把原本的Subscription改名成了Disposable。

除了上一節裡subscribe(Subscriber )方法返回void,其他名為subscribe的方法都返回Disposable

相應的,

  • CompositeSubscription 改名成了 CompositeDisposable
  • SerialSubscription 和 MultipleAssignmentSubscription被合併到了SerialDisposable裡. set() 方法會處理掉就的值,而replace()方法不會。
  • RefCountSubscription被移除了

這裡寫圖片描述

Backpressure

在第一節Observable and Flowable裡已經說到了這個問題,在2中,Observable將不會處理backpressure,也就不會發生MissingBackpressureException問題,但記憶體仍然會快取多餘的資料。

而在使用Flowable時,如果配置Backpressure有問題,那麼MissingBackpressureException依然存在。

Schedulers

RxJava2裡仍然包含了computation, io, newThread 和 trampoline這些預設執行緒排程。而immediate被移除了,因為他經常被人錯誤使用。同時Schedulers.test也被移除了。

Entering the reactive world

將普通方法轉換成RxJava的資料來源,在RxJava1中,提供了Observable.create()方法,但是這個方法過於強大,但使用時需要注意的東西太多經常會發生錯誤。

因此在RxJava2中,把原來的fromAsync重新命名成了create,fromAsync是一個和create類似但更為簡單和安全的方法。這樣大部分舊程式碼都能夠繼續使用。

Leaving the reactive world

之前如果想把資料來源轉換成普通的資料物件,需要先轉換成BlockingObservable。而在Rxjava2中,可以呼叫blockingXXX方法直接把資料來源轉換成物件:

List<Integer> list = Flowable.range(1, 100).toList().blockingFirst();
  • 1
  • 2
  • 1
  • 2

有一點需要特別注意,在RxJava2裡,不建議在Subscriber裡丟擲錯誤,這意味著下面的程式碼可能有一天就不能繼續執行了:

Subscriber<Integer> subscriber = new Subscriber<Integer>() {
    @Override
    public void onSubscribe(Subscription s) {
        s.request(Long.MAX_VALUE);
    }

    public void onNext(Integer t) {
        if (t == 1) {
            throw new IllegalArgumentException();
        }
    }

    public void onError(Throwable e) {
        if (e instanceof IllegalArgumentException) {
            throw new UnsupportedOperationException();
        }
    }

    public void onComplete() {
        throw new NoSuchElementException();
    }
};

Flowable.just(1).subscribe(subscriber);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

由於上面類似的程式碼實際中出現得很多,因此在2中提供了safeSubscribe方法,使用它就可以繼續在subscriber裡丟擲錯誤。

當然,你可以繞過subscribe(subscriber)這個方法,使用類似:

Flowable.just(1).subscribe(subscriber::onNext, subscriber::onError, subscriber::onComplete);
  • 1
  • 1

這樣的方法,之前的程式碼仍然可以繼續throw錯誤。

Operator differences

https://github.com/ReactiveX/RxJava/wiki/What’s-different-in-2.0#1x-observable-to-2x-flowable 
整合和過載方法,例如新增加,存在著相當大的變化。

總結

可以明顯的看到,RxJava2最大的改動就是對於backpressure的處理,為此將原來的Observable拆分成了新的Observable和Flowable,同時其他相關部分也同時進行了拆分。

原文連結:http://www.jianshu.com/p/850af4f09b61

3
 
0

相關文章