RxJava2與RxJava1的簡單對比
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,同時其他相關部分也同時進行了拆分。
- 頂
- 踩
相關文章
- Rxjava1升級到Rxjava2的工作RxJava
- ListView 與 RecyclerView 簡單對比View
- RxJava1 升級到 RxJava2 所踩過的坑RxJava
- Rxjava2的簡單使用與基本操作符RxJava
- nginx與lighttpd效能簡單對比薦Nginxhttpd
- 使用 Flex 佈局與其他普通佈局的簡單對比Flex
- Kotlin和Java的簡單對比KotlinJava
- ROWID與ROWNUM的簡介與對比
- 日誌收集工具簡單對比
- 簡單介紹SpringSecurity框架簡介及與shiro特點對比SpringGse框架
- Python實現簡單的excel對比工具PythonExcel
- React 中的新舊 Context 簡單對比ReactContext
- Oracle/MySQL/PostgreSQL 簡單查詢的效能對比OracleMySql
- EasyReact的簡單試用及和RAC的對比React
- Delphi寫的讀狗程式的簡單逆向對比.
- Play框架與NodeJS的簡單比較框架NodeJS
- 【OpenCv】OpenCv原始版本與新版本(2.4.10)的一個簡單對比OpenCV
- 簡單對比git pull和git pull --rebase的使用Git
- HTTPS SPDY和 HTTP/2效能的簡單對比HTTP
- 基於RxJava2實現的簡單圖片爬蟲RxJava爬蟲
- Google Guice 與 Noear Solon 的簡單對照GoGUI
- 對比SQL中簡單巢狀查詢與非巢狀查詢CFSQL巢狀
- 簡單對比測試了幾個基於 swoole 的框架框架
- 簡單對比一下CORS跨域與Nginx反向代理跨域優劣CORS跨域Nginx
- synchronized 與 Lock 的對比synchronized
- 【HTML與XML的對比】HTMLXML
- 簡單對比MySQL和Oracle中的一個sql解析細節MySqlOracle
- Oracle 和 mysql 的一些簡單命令對比參照(轉)OracleMySql
- 歸併排序與快速排序的簡明實現及對比排序
- 對CSRF的簡單理解
- RxJava2 系列-1:一篇的比較全面的 RxJava2 方法總結RxJava
- mongodb和hbase的簡單比較MongoDB
- Go 與 C++ 的對比和比較GoC++
- TDSQL-A與CK的對比SQL
- Mobx 與 Redux 的效能對比Redux
- OSI與TCP/IP的對比TCP
- 字串-簡單字串比較字串
- Python中x=y與x==y的區別。(比較簡單)Python