基礎概念
RxJava是一個在基于Java VM擴展的使用可觀測的序列來組成異步的、基于事件的程序的庫。它基于觀察者模式支持數據和事件的流式流通處理,并增加了多種運算符以在多種場景下整合事件和數據。抽象了低級別的線程、同步、并發API。
- 響應式編程(Reactive Programming)是一種面向數據流和變化傳播的編程范式。這意味著可以在編程語言中很方便地表達靜態或動態的數據流,而相關的計算模型會自動將變化的值通過數據流進行傳播。
- 函數式編程是也一種編程范式,它將函數視為一等公民,意味著函數和其他類型數據有同等的地位,可以作為函數的參數、返回值使用(高階函數)。
- 被觀察者,Observable/Flowable
- 觀察者,Observer/Consumer/Subscriber
- 上游:發射事件的地方,對應的是被訂閱者(Observable/Flowable)
- 下游:接收事件的地方,對應的是觀察者(Observer/Subscriber)
使用
1. 創建被觀察者(上游對象,Observable/Flowable)
Observable<String> observable = Observable.fromArray(new String[]{"A","B","C"});
2.創建觀察者(下游對象,Observer/Consumer)
//創建一個Observer
Observer<String> observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
System.out.println("Thread:" + Thread.currentThread() + "|" + "accept:"+ s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
//創建一個Consumer
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("Thread:" + Thread.currentThread() + "|" + "onNext:"+ s);
}
};
Consumer和Observer的不同之處在于Consumer不關心onNext()和onError()方法,它只管處理上游發送的數據。
3.訂閱
訂閱通過方法subscribe()實現,當一個被觀察者收到一個訂閱請求時,他就會開始發送一遍事件。所以下面2次subscribe動作,observable發送了2遍事件。
observable.subscribe(observer);
observable.subscribe(consumer);
>>>輸出:
Thread:Thread[main,5,main]|onNext:A
Thread:Thread[main,5,main]|onNext:B
Thread:Thread[main,5,main]|onNext:C
Thread:Thread[main,5,main]|accept:A
Thread:Thread[main,5,main]|accept:B
Thread:Thread[main,5,main]|accept:C
4.使用調度器(Schedulers)指定上下游執行線程
在開發過程中,我們經常需要把一些耗時動作放在后臺線程中進行,然后將結果放到主線程中處理。
在RxJava中可以使用調用器的subscribeOn指定在哪個線程發生訂閱(及上游)
和observeOn用于指定在哪個線程發生觀察(即下游)
從而實現這樣的功能。我們先把上游指定到newThread中執行,任務為每隔一秒發送一個數字。
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
for (int i = 0; i < 3; i++) {
System.out.println("Thread:" + Thread.currentThread() + "|" + "emit:" + i);
emitter.onNext(i + "");
Thread.sleep(1000);
}
}
}).subscribeOn(Schedulers.newThread()).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("Thread:" + Thread.currentThread() + "|" + "accept:"+ s);
}
});
>>>輸出:
Process finished with exit code 0
奇怪的是根據console看到上游發送任何事件,下游更沒有接收到任何事件。這是因為:
在RxJava中默認的調度器運行在守護線程上
,這意味著只要Java主線程退出,所有這些默認的調度器會停止。本段代碼中上游運行在子線程中處理耗時操作,下游運行在主線程中,上游還沒開始發送消息,下游的主線程已經結束任務了,所以調度器來不及調度也就停止了。現在我們讓上游運行在默認的主線程中,下游運行在子線程中:
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
for (int i = 0; i < 3; i++) {
System.out.println("Thread:" + Thread.currentThread() + "|" + "emit:" + i);
emitter.onNext(i + "");
Thread.sleep(1000);
}
}
}).observeOn(Schedulers.newThread()).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("Thread:" + Thread.currentThread() + "|" + "accept:"+ s);
}
});
>>>輸出:
Thread:Thread[main,5,main]|emit:0
Thread:Thread[RxNewThreadScheduler-1,5,main]|accept:0
Thread:Thread[main,5,main]|emit:1
Thread:Thread[RxNewThreadScheduler-1,5,main]|accept:1
Thread:Thread[main,5,main]|emit:2
Thread:Thread[RxNewThreadScheduler-1,5,main]|accept:2
5.結合操作符實現數據操作
我們知道RxJava有多種操作符可以操作流中的數據,下面是一個例子,假設學生的姓名和成績來自兩個接口,我們需要等這個接口都返回結果時,才刷新界面,看用下面這demo代碼,需要注意將2個接口請求放到子線程中,否則2個模擬請求默認會在主線程中,進行串行調用。(可以看兩個log的時間間隔)
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import java.util.HashMap;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
public class TestOperatorActivity extends Activity {
private String TAG = "TestOP";
class Stu {
String name;
int scoreMath, scoreEnglish;
public Stu(String name, int scoreMath, int scoreEnglish) {
this.name = name;
this.scoreMath = scoreMath;
this.scoreEnglish = scoreEnglish;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.rx_act_test_operator);
findViewById(R.id.btnTestZip).setOnClickListener(v -> testZip());
}
void testZip() {
TextView tvName = findViewById(R.id.tvName);
TextView tvScoreEnglish = findViewById(R.id.tvScoreEnglish);
TextView tvScoreMath = findViewById(R.id.tvScoreMath);
Observable nameTask = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
//模擬請求耗時
Thread.sleep(1000);
emitter.onNext("小王");
Log.d(TAG, "Thread:" + Thread.currentThread() + "發送姓名");
}
}).subscribeOn(Schedulers.newThread()); //注意將該模擬請求指定到子線程中,模擬并行請求
Observable scoreTask = Observable.create(new ObservableOnSubscribe<HashMap<String, Integer>>() {
@Override
public void subscribe(ObservableEmitter<HashMap<String, Integer>> emitter) throws Exception {
//模擬請求耗時
Thread.sleep(5000);
HashMap map = new HashMap();
map.put("scoreEnglish", 80);
map.put("scoreMath", 95);
Log.d(TAG, "Thread:" + Thread.currentThread() + "發送成績");
emitter.onNext(map);
}
}).subscribeOn(Schedulers.newThread()); //注意將該模擬請求指定到子線程中,模擬并行請求
Observable.zip(nameTask, scoreTask, new BiFunction<String, HashMap<String, Integer>, Stu>() {
@Override
public Stu apply(String s, HashMap<String, Integer> stringIntegerHashMap) throws Exception {
Log.d(TAG, "Thread:" + Thread.currentThread() + "合并數據");
return new Stu(s, stringIntegerHashMap.get("scoreMath"), stringIntegerHashMap.get("scoreEnglish"));
}
}).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Stu>() {
@Override
public void accept(Stu stu) throws Exception {
Log.d(TAG, "Thread:" + Thread.currentThread() + "收到最終數據");
tvName.setText(stu.name);
tvScoreEnglish.setText(stu.scoreEnglish + "");
tvScoreMath.setText(stu.scoreMath + "");
}
});
}
}
>>>輸出,觀察“發送姓名”和“發送成績”的時間間隔為4秒,且不再同一線程中執行,說明他們是并行進行的。
14:12:35.455 20450-20516/com.ebm.rxjava D/TestOP: Thread:Thread[RxNewThreadScheduler-2,5,main]發送姓名
14:12:39.456 20450-20517/com.ebm.rxjava D/TestOP: Thread:Thread[RxNewThreadScheduler-3,5,main]發送成績
14:12:39.456 20450-20517/com.ebm.rxjava D/TestOP: Thread:Thread[RxNewThreadScheduler-3,5,main]合并數據
14:12:39.461 20450-20450/com.ebm.rxjava D/TestOP: Thread:Thread[main,5,main]收到最終數據
調度器
RxJava操作符不直接和Threads或者ExecutorServices打交道,而是通過Schedulers(調度器)的通用API來實現對具體并發代碼的抽象。RxJava通過工具類Schedulers提供了幾個標準的調度方式
RxJava operators don't work with Thread
s or ExecutorService
s directly but with so called Scheduler
s that abstract away sources of concurrency behind a uniform API. RxJava 2 features several standard schedulers accessible via Schedulers
utility class.
-
Schedulers.computation()
: 在后臺的固定數量的專用線程上運行計算密集型工作。大多數異步操作符使用這個作為默認的調度器Run computation intensive work on a fixed number of dedicated threads in the background. Most asynchronous operator use this as their default
Scheduler
. -
Schedulers.io()
: 在一個動態線程集合上運行類似I/O或阻塞的操作。Run I/O-like or blocking operations on a dynamically changing set of threads.
-
Schedulers.single()
: 以順序和FIFO方式在單個線程上運行工作。Run work on a single thread in a sequential and FIFO manner.
-
Schedulers.trampoline()
: ???在一個參與線程中以順序和FIFO方式運行工作,通常用于測試目的。Run work in a sequential and FIFO manner in one of the participating threads, usually for testing purposes.
其他
Consumer、Observer、Publisher
Consumer和Observer都是接口,只是Consumer中只有一個accept方法,而Observer中有onNex、onComplete、onError、onSubsribe(Disposable d)四個個方法。其中onSubscribe中的Disposable可以用來作為上下游的開關,調用Disposable.dispose()可以停止接收上游發送的事件。
Publisher能夠提供一個無邊際數量的對象序列,當收到訂閱請求時發布這些無數量限制的元素。Flowable繼承自Publisher。
onNext、onComplete、onError
? 這三個方法是Emitter(發射器)接口中定義的三個方法,分別表示事件發送、完成、異常。
- 上游可以發送無限個onNext, 下游也可以接收無限個onNext.
- 當上游發送了一個onComplete后, 上游onComplete之后的事件將會
繼續
發送, 而下游收到onComplete事件之后將不再繼續
接收事件. - 當上游發送了一個onError后, 上游onError之后的事件將
繼續
發送, 而下游收到onError事件之后將不再繼續
接收事件. - 上游可以不發送onComplete或onError.
- 最為關鍵的是onComplete和onError必須唯一并且互斥, 即不能發多個onComplete, 也不能發多個onError, 也不能先發一個onComplete, 然后再發一個onError, 反之亦然
- 注: 關于onComplete和onError唯一并且互斥這一點, 是需要自行在代碼中進行控制, 如果你的代碼邏輯中違背了這個規則, **并不一定會導致程序崩潰. ** 比如發送多個onComplete是可以正常運行的, 依然是收到第一個onComplete就不再接收了, 但若是發送多個onError, 則收到第二個onError事件會導致程序會崩潰。
并行處理
在RxJava中并行處理,體現在在不同的獨立的flow中進行計算的結果,最終被合并到一個flow中去。以flowMap為例:
Flowable.range(1, 10)
.flatMap(v -> Flowable.just(v).subscribeOn(Schedulers.computation()).map(w -> w * w) )
.blockingSubscribe(v -> Log.d(TAG, String.valueOf(v)));
>>>輸出:
05:58:40.317 D/TestOP: 1
05:58:40.317 D/TestOP: 9
05:58:40.317 D/TestOP: 25
05:58:40.317 D/TestOP: 49
05:58:40.318 D/TestOP: 81
05:58:40.318 D/TestOP: 4
05:58:40.318 D/TestOP: 16
05:58:40.320 D/TestOP: 36
05:58:40.321 D/TestOP: 64
05:58:40.321 D/TestOP: 100
背壓
當上下游在不同的線程中,發射和接收數據的速率可能有所不同,為了避免超出預期的內存開銷,或者為了滿足跳過、舍棄某些數據的需求,所謂的背壓就產生了。背壓是一種不同操作能夠表達他們能處理多少數據的流控制機制。背壓用來在不知道上游將會發送多少數據量的時候,用來限制內存開銷的。RxJava的Flowable是專門用來處理背壓的。
Flowable.create(new FlowableOnSubscribe<String>(){
@Override
public void subscribe(FlowableEmitter<String> emitter) throws Exception {
for(int i=0;i<1000;i++) {
emitter.onNext(i + "");
}
}
}, BackpressureStrategy.ERROR).subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Thread.sleep(1000);
Log.e(TAG,"處理數據" + s);
}
});
Flowable將數據對象發送到一個大小為128的緩沖區內,等待下游線程從該緩存區中取出數據對象進行處理后,等緩沖區有空閑位置時,再將數據對象放置到緩沖區內。如果此時,下游對象沒有使用request(long n)從緩存區拉取數據,那么此時有幾種不同的背壓策略(BackpressureStrategy可供選擇):
/**
* Represents the options for applying backpressure to a source sequence.
*/
public enum BackpressureStrategy {
/**
* OnNext events are written without any buffering or dropping.
* Downstream has to deal with any overflow.
* <p>Useful when one applies one of the custom-parameter onBackpressureXXX operators.
*/
MISSING,
/**
* Signals a MissingBackpressureException in case the downstream can't keep up.
*/
ERROR,
/**
* Buffers <em>all</em> onNext values until the downstream consumes it.
*/
BUFFER,
/**
* Drops the most recent onNext value if the downstream can't keep up.
*/
DROP,
/**
* Keeps only the latest onNext value, overwriting any previous value if the
* downstream can't keep up.
*/
LATEST
}
RxJavaPlugins
API文檔定義:Utility class to inject handlers to certain standard RxJava operations.
簡單來說,RxJavaPlugins提供了一種讓我們通過hook的方式自定義RxJava行為的途徑
。首先查看該類的源碼,可以看到所有的方法對象都是static
的,我們通過如下方式設置RxJavaPlugins的靜態成員變量:
RxJavaPlugins.setOnMaybeSubscribe(new BiFunction<Maybe, MaybeObserver, MaybeObserver>() {
@Override
public MaybeObserver apply(Maybe maybe, MaybeObserver maybeObserver) throws Exception {
return new MyCustomMaybeObserver(maybeObserver); //這個maybeObserver就是我們真正的下游
}
});
再來看一段Maybe的最終subscribe的源碼:
//Maybe.subscribe(MaybeObserver<? super T> observer)
public final void subscribe(MaybeObserver<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null MaybeObserver. Please check the handler provided to RxJavaPlugins.setOnMaybeSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");
try {
subscribeActual(observer);
} catch (NullPointerException ex) {
throw ex;
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
NullPointerException npe = new NullPointerException("subscribeActual failed");
npe.initCause(ex);
throw npe;
}
}
從上面可以看出,subscriberActural(observer)中的observer是經過RxJavaPlugins進行處理后得到的observer,再看RxJavaPlugins.onSubscribe(this,observer)代碼:
//RxJavaPlugins.onSubscribe(@NonNull Maybe<T> source, @NonNull MaybeObserver<? super T> observer)
public static <T> MaybeObserver<? super T> onSubscribe(@NonNull Maybe<T> source, @NonNull MaybeObserver<? super T> observer) {
BiFunction<? super Maybe, ? super MaybeObserver, ? extends MaybeObserver> f = onMaybeSubscribe; //這個onMaybeSubscribe就是前面說的RxJavaPlugins的靜態變量
if (f != null) {
return apply(f, source, observer);
}
return observer;
}
所以,可以把RxJavaPlugins理解為一個存儲自定義observe行為的地方,在對Observerable、Maybe、Single等進行observe時,會判斷RxJavaPlugins中是否定義過自定義的Observer,如果有就進行apply操作之后返回新的Observer,否則原樣返回。
本段參考:給初學者的RxJava2.0教程(十)
RxJava與RxAndroid
- RxAndroid是RxJava的一個針對Android平臺的擴展,主要用于 Android 開發。
- RxAndroid只是在RxJava的基礎上添加了少數的幾個類,目的是能夠在Android中更簡單的使用RxJava,特別提供了可以指定到Android主線程的Scheduler,除此之外還增加了基于RxJavaPlugins的擴展RxAndroidPlugins。
操作符
操作符分為創建、轉換、延時、條件、過濾這幾大類。
轉換操作符
map
將輸入對象經過Function<SourceType,TargetType>從SourceType轉換為TargetType:
Observable.fromArray(new String[]{"A","B","C"})
.map(new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
return s + "_" + s;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println(s);
}
});
>>>輸出:
A_A
B_B
C_C
flatMap
和map類似對流過的數據做轉換,只是flatMap會將數據轉換成ObservableSource類型的數據對象,被轉換的流被分散到多個并行執行的ObservableSource中,所以不能保證執行的順序。
Flowable.range(1, 10)
.flatMap(v -> Flowable.just(v).subscribeOn(Schedulers.computation()).map(w -> w * w) )
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG, String.valueOf(integer));
}
});
>>>輸出:
D/TestOP: 1
D/TestOP: 9
D/TestOP: 4
D/TestOP: 16
D/TestOP: 49
D/TestOP: 64
D/TestOP: 81
D/TestOP: 100
D/TestOP: 25
D/TestOP: 36
concatMap
Flowable.range(1, 10)
.concatMap(v -> Flowable.just(v).subscribeOn(Schedulers.computation()).map(w -> w * w) )
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG, String.valueOf(integer));
}
});
D/TestOP: 1
D/TestOP: 4
D/TestOP: 9
D/TestOP: 16
D/TestOP: 25
D/TestOP: 36
D/TestOP: 49
D/TestOP: 64
D/TestOP: 81
D/TestOP: 100
zip
合并多個事件流(Observable),生成一個新的事件流(Observable)。最終合并的事件流的事件數有前面被合并的事件流中事件個數最少的決定。舉一個請求兩個耗時數據的例子:
void testZip() {
TextView tvName = findViewById(R.id.tvName);
TextView tvScoreEnglish = findViewById(R.id.tvScoreEnglish);
TextView tvScoreMath = findViewById(R.id.tvScoreMath);
Observable nameTask = Observable.create((ObservableOnSubscribe<String>)
emitter -> {
Thread.sleep(1000); //模擬耗時
emitter.onNext("小王");
Log.d(TAG, "Thread:" + Thread.currentThread() + "發送姓名");
}).subscribeOn(Schedulers.newThread());
Observable scoreTask = Observable.create((ObservableOnSubscribe<HashMap<String, Integer>>)
emitter -> {
Thread.sleep(5000); //模擬耗時
HashMap map = new HashMap();
map.put("scoreEnglish", 80);
map.put("scoreMath", 95);
Log.d(TAG, "Thread:" + Thread.currentThread() + "發送成績");
emitter.onNext(map);
}).subscribeOn(Schedulers.newThread());
Observable.zip(nameTask, scoreTask, (BiFunction<String, HashMap<String, Integer>, Stu>)
(s, stringIntegerHashMap) -> {
Log.d(TAG, "Thread:" + Thread.currentThread() + "合并數據");
return new Stu(s, stringIntegerHashMap.get("scoreMath"), stringIntegerHashMap.get("scoreEnglish"));
}).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
.subscribe((Consumer<Stu>) stu -> {
Log.d(TAG, "Thread:" + Thread.currentThread() + "收到最終數據");
tvName.setText(stu.name);
tvScoreEnglish.setText(stu.scoreEnglish + "");
tvScoreMath.setText(stu.scoreMath + "");
});
}
merge
將2個并行進行的事件流合并到一個事件流中,按時間順序執行。
void testMerge() {
Observable observable1 = Observable.interval(1000l,TimeUnit.MILLISECONDS).take(3);
Observable observable2 = Observable.interval(2000l,TimeUnit.MILLISECONDS).take(3);
Observable.merge(observable1,observable2).subscribe(new Consumer<Long>() {
@Override
public void accept(Long i) throws Exception {
Log.d(TAG,i.toString());
}
});
}
//輸出:
17:42:42.555 D/TestOP: 0
17:42:43.554 D/TestOP: 1
17:42:43.555 D/TestOP: 0
17:42:44.555 D/TestOP: 2
17:42:45.555 D/TestOP: 1
17:42:47.555 D/TestOP: 2
concat
Observable observable1 = Observable.interval(1000l,TimeUnit.MILLISECONDS).take(3);
Observable observable2 = Observable.interval(2000l,TimeUnit.MILLISECONDS).take(3);
Observable.concat(observable1,observable2).subscribe(new Consumer<Long>() {
@Override
public void accept(Long i) throws Exception {
Log.d(TAG,i.toString());
}
});
>>>輸出:
17:46:18.587 D/TestOP: 0
17:46:19.587 D/TestOP: 1
17:46:20.587 D/TestOP: 2
17:46:22.588 D/TestOP: 0
17:46:24.588 D/TestOP: 1
17:46:26.588 D/TestOP: 2
延時操作符
delay
使事件流經過一段時間延遲后再開始執行
void testDelay() {
Log.d(TAG,"TestDelay");
Observable.fromArray(new String[]{"A","B","C"})
.delay(2000, TimeUnit.MILLISECONDS)
.subscribe(s -> Log.d(TAG,s));
}
>>>輸出:
05:53:34.615 D/TestOP: TestDelay
05:53:36.643 D/TestOP: A
05:53:36.643 D/TestOP: B
05:53:36.643 D/TestOP: C
interval
在經過最初的延時(initialDelay)開始從0L發送數據,每次經過一個時間間隔(period),發送一個增大的數字。
Returns an Observable that emits a {@code 0L} after the {@code initialDelay} and ever increasing numbers after each {@code period} of time thereafter, on a specified {@link Scheduler}.
Observable.interval(1000l,TimeUnit.MILLISECONDS).subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.d(TAG, String.valueOf(aLong));
}
});
>>>輸出:
0
1
2
4
5
6
...
skip
跳過事件序列的前n項,以interval的代碼為基礎,跳過前面10項
Observable.interval(1000l,TimeUnit.MILLISECONDS).skip(10).subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.d(TAG, String.valueOf(aLong));
}
});
>>>輸出:
10
11
12
13
14
15
...
take
只取事件序列的前N項,以skip的代碼為基礎,跳過前10項后,取5項
Observable.interval(1000l,TimeUnit.MILLISECONDS).skip(10).take(5)subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.d(TAG, String.valueOf(aLong));
}
});
>>>輸出:
10
11
12
13
14
defer
**直到有觀察者(Observer)訂閱時,才動態創建觀察者對象(Observable) **
int i = 1;
void testDefer() {
Observable<Integer> observable = Observable
.defer((Callable<ObservableSource<Integer>>) () -> Observable.just(i));
i = 2;
observable.subscribe(it -> Log.d(TAG,it.toString()));
}
>>>輸出:2
過濾操作符
filter
Flowable.range(0,10).filter(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) throws Exception {
if(integer.intValue() % 2 == 0) {
return true;
}
return false;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG,integer.toString());
}
});
>>>輸出:
0
2
4
6
8
組合使用
定時發送自定義事件
//可以使用from+interval+zip實現
/**
* 測試固定時間間隔發送自定義消息
*/
void testIntervalCustomMsg() {
Observable.zip(Observable.fromArray(new String[]{"A","B","C"})
,Observable.interval(3000l,TimeUnit.MILLISECONDS)
,new BiFunction<String,Long,String>(){
@Override
public String apply(String s, Long aLong) throws Exception {
return s;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String o) throws Exception {
Log.d(TAG,o.toString());
}
});
}
最后,來一張別人整理的操作符大全圖片(原地址:http://www.lxweimin.com/p/12883e1b59f9)
參考: