RxJava2是个好东西,多样的操作符更是体现其灵活性的重要元素之一。
记一些常用的操作符,以免到用的时候抓瞎。
create
create自不必说,最原生的创建Observable的方式,onNext/onComplete/onError可完全自由控制。
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {
String s = "I'm RxJava2";
observableEmitter.onNext(s);
observableEmitter.onComplete();
}
}).subscribe(new DisposableObserver<String>() {
@Override
protected void onStart() {
System.out.println("----start----");
}
@Override
public void onNext(String s) {
System.out.println("onNext: "+s);
}
@Override
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("----end----");
}
});
just/fromArray/fromIterable/range
用于创建发送多个数据的Observable。
just重载了多个参数数量不同的方法,最大可带10个参数,just同样是调用的fromArray方法;
public static <T> Observable<T> just(T item1, T item2, T item3, T item4, T item5, T item6, T item7, T item8, T item9, T item10) ;
Observable.just("a");
Observable.just("a", "b");
fromArray方法参数为可变长参数,因此既可传数组,也可传多个参数;
public static <T> Observable<T> fromArray(T... items)
String[] strings = {"a", "b", "c"};
Observable.fromArray(strings);
Observable.fromArray("a", "b", "c");
Observable.fromArray(1, 2, 3, 4);
fromIterable方法参数为实现Iterable接口的类,一般为JDK中的List/Map/Set等集合类;
public static <T> Observable<T> fromIterable(Iterable<? extends T> source)
String[] strings = {"aa12", "bb34", "cc56"};
List<String> listString = Arrays.asList(strings);
Observable.fromIterable(listString);
range用于快速发送多个整数,count为发送的数量而非终止范围;
public static Observable<Integer> range(int start, int count)
public static Observable<Long> rangeLong(long start, long count)
//发送从10开始的整数,发送4个(发到13)
Observable.range(10, 4);
//发送从10开始的长整型数,发送6个(发到15)
Observable.rangeLong(10, 6);
repeat/retry
用于重复Observable的发送行为。
repeat默认重复次数为Long.MAX_VALUE,可使用重载方法指定次数以及使用repeatUntil指定条件;
//一直重复
Observable.fromArray(1, 2, 3, 4).repeat();
//重复发送5次
Observable.fromArray(1, 2, 3, 4).repeat(5);
//重复发送直到符合条件时停止重复
Observable.fromArray(1, 2, 3, 4).repeatUntil(new BooleanSupplier() {
@Override
public boolean getAsBoolean() throws Exception {
//自定判断条件,为true即可停止,默认为false
return false;
}
});
retry需要触发onError方法才会重复发送数据,重载方法和repeat大同小异;
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {
for (int i = 0; i < 10; i++) {
observableEmitter.onNext(i+"");
if(i==8){
// 发送onError,触发retry
observableEmitter.onError(new Exception("It's my fault"));
}
}
observableEmitter.onComplete();
}
});
//一直重试
observable.retry();
//重试3次
observable.retry(3);
//一直重试直到符合条件后停止重试
observable.retryUntil(new BooleanSupplier() {
@Override
public boolean getAsBoolean() throws Exception {
//自定判断条件,为true则停止重复
return false;
}
});
interval/timer/delay
用于定时/延时发送整数,即onNext会定时/延时调用。
interval用于定时发送,如果未传initialDelay则initialDelay=period,而非为0;
intervalRange是range与interval的结合,可定时发送某范围的整数;
public static Observable<Long> interval(long period, TimeUnit unit)
public static Observable<Long> interval(long initialDelay, long period, TimeUnit unit)
public static Observable<Long> intervalRange(long start, long count, long initialDelay, long period, TimeUnit unit)
//每3秒发个自增整数
Observable.interval(3, TimeUnit.SECONDS);
//初始延时1秒,每3秒发一个自增整数
Observable.interval(1, 3, TimeUnit.SECONDS);
//初始延时2秒,后每1秒发一个从10开始的整数,发5个(发到14)停止
Observable.intervalRange(10, 5, 2, 1, TimeUnit.SECONDS);
timer用于延时发送;
public static Observable<Long> timer(long delay, TimeUnit unit)
//延时3秒后,发送一个整数0
Observable.timer(3, TimeUnit.SECONDS);
delay用于延时发送,区别在于delay产生泛型Observable,要使用于已经生成的Observable才能起作用;
public final Observable<T> delay(long delay, TimeUnit unit)
//延时3秒后,发送"1""2""3"
Observable.just("1","2","3").delay(3,TimeUnit.SECONDS);
map/scan/flatMap/concatMap
用于转换数据。
map利用Function将T转为R;
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper)
下面的代码将字符串转为了整数,并且放大了10倍;
Observable.just("1", "2", "3").map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
return Integer.valueOf(s) * 10;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer);
}
});
输出即为:
10
20
30
scan仅针对一个Observable的数据;
public final Observable<T> scan(BiFunction<T, T, T> accumulator)
Observable.just(1, 2, 3, 4).scan(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer integer1, Integer integer2) throws Exception {
System.out.println("i1=" + integer1 + ",i2=" + integer2);
return integer1 + integer2;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer);
}
});
输出为:
1
i1=1,i2=2
3
i1=3,i2=3
6
i1=6,i2=4
10
flatMap/concatMap与map类似,不过是将数据拆分成多个Observable,其中concatMap是可以保证顺序的(即不受delay等延时影响);
public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper)
public final <R> Observable<R> concatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper)
下面的代码将两个字符串发送出去,转换成两个Observable,并在Observable中使用map转换为了整数,并放大了100倍再发送下去;
Observable.just("123", "456").flatMap(new Function<String, ObservableSource<Integer>>() {
@Override
public ObservableSource<Integer> apply(String s) throws Exception {
System.out.println("apply:" + s);
String[] strings = s.split("");
//产生新的Observable
return Observable.fromArray(strings).map(new Function<String, Integer>() {
@Override
public Integer apply(String strings) throws Exception {
return Integer.valueOf(strings) * 100;
}
});
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer);
}
});
输出为:
apply:123
100
200
300
apply:456
400
500
600
merge/concat/zip
用于组合或连接多个Observable。
merge组合Observable无法顾及顺序,重载方法中最大可传入4个Observable,或直接使用实现Iterable接口的集合;
merge内部使用的是flatMap,因此无法顾及顺序是应有之意;
public static <T> Observable<T> merge(Iterable<? extends ObservableSource<? extends T>> sources)
public static <T> Observable<T> merge(ObservableSource<? extends T> source1, ObservableSource<? extends T> source2)
concat与merge类似,不过内部使用的concatMap,因此可以保证顺序;
public static <T> Observable<T> concat(Iterable<? extends ObservableSource<? extends T>> sources)
下列代码使用concat,在第一个Observable有3秒延时的情况下,会等待3秒后依次发送两个Observable;而merge则会先发送未延时的Observable,再等待3秒延时后发送另一个Observable;
Observable.concat(Observable.just("1", "2", "3").delay(3, TimeUnit.SECONDS), Observable.just("11", "22", "33")).subscribe(new DisposableObserver<String>() {
@Override
protected void onStart() {
System.out.println(System.currentTimeMillis());
}
@Override
public void onNext(String s) {
System.out.println(System.currentTimeMillis());
System.out.println(s);
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
System.out.println("--------");
}
});
1555660573710
1555660576718
1
1555660576718
2
1555660576719
3
1555660576719
11
1555660576719
22
1555660576719
33
--------
zip会通过Function组合多个Observable的数据再行发送;
BiFunction泛型参数个数根据Observable的个数变化,始终比Observable的个数大1个,R即"Result"的缩写,代指结果的泛型;
重载方法中最大可直接传9个Observable进行组合,也就是有9个泛型;
如果Observable过多,则使用zipIterable或zipArray;
public static <T1, T2, R> Observable<R> zip(ObservableSource<? extends T1> source1, ObservableSource<? extends T2> source2, BiFunction<? super T1, ? super T2, ? extends R> zipper)
public static <T, R> Observable<R> zipIterable(Iterable<? extends ObservableSource<? extends T>> sources, Function<? super Object[], ? extends R> zipper, boolean delayError, int bufferSize)
public static <T, R> Observable<R> zipArray(Function<? super Object[], ? extends R> zipper, boolean delayError, int bufferSize, ObservableSource... sources)
下列代码组合两个Observable,并对其数据进行一定处理;
Observable.zip(Observable.just("1", "2", "3"), Observable.just(10, 100, 1000), new BiFunction<String, Integer, Integer>() {
@Override
public Integer apply(String s, Integer integer) throws Exception {
return Integer.valueOf(s) * integer;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer);
}
});
输出为:
10
200
3000
filter/distinct
用于过滤数据。
filter只有一个方法,使用Predicate定制过滤条件;
public final Observable<T> filter(Predicate<? super T> predicate)
下列代码只保留了偶数;
Observable.just(1, 2, 3, 4).filter(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) throws Exception {
return integer % 2 == 0;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer);
}
});
输出为:
2
4
distinct用于过滤重复数据,内部使用的HashSet,又因为HashSet也是使用HashMap实现的,因此可以理解为distinct将数据的值作为HashMap的Key存入,自然可以过滤掉相同的Key;
不带参数的distinct方法默认以值的hashCode为key;
distinctUntilChanged方法指key变化时才会保留,指相邻数据的key变化;
public final Observable<T> distinct()
public final <K> Observable<T> distinct(Function<? super T, K> keySelector)
public final Observable<T> distinctUntilChanged()
public final <K> Observable<T> distinctUntilChanged(Function<? super T, K> keySelector)
public final Observable<T> distinctUntilChanged(BiPredicate<? super T, ? super T> comparer)
//过滤掉了“bb",其他保留
Observable.just("aa", "bb", "ccc", "dd", "bb").distinct();
//只保留了两个长度不一样的值,"aa""ccc"
Observable.just("aa", "bb", "ccc", "dd", "bb").distinct(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
//以字符串长度为key
return s.length();
}
});
//都保留了,因为相邻的hashCode都不一样
Observable.just("aa", "bb", "ccc", "dd", "bb").distinctUntilChanged();
//以字符串长度为Key,保留了"aa""ccc""dd"
Observable.just("aa", "bb", "ccc", "dd", "bb").distinctUntilChanged(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
return s.length();
}
})
//长度相等就过滤掉,等价于上面条件,因此保留了"aa""ccc""dd"
Observable.just("aa", "bb", "ccc", "dd", "bb").distinctUntilChanged(new BiPredicate<String, String>() {
@Override
public boolean test(String s1, String s2) throws Exception {
return s1.length() == s2.length();
}
})
take/skip
用于取得或跳过数据。
take有一系列取数据的方法,取前count个数据或取后count个数据,也可以通过重载方法取某个time时间内的数据;
takeUntil会一直取数据,直到条件成立后不再取;
takeWhile会在条件成立时取数据,直到不再成立;
public final Observable<T> take(long count)
public final Observable<T> take(long time, TimeUnit unit)
public final Observable<T> takeLast(int count)
public final Observable<T> takeLast(long count, long time, TimeUnit unit)
public final Observable<T> takeUntil(Predicate<? super T> stopPredicate)
public final Observable<T> takeWhile(Predicate<? super T> predicate)
值得注意的是,takeLast或其他XXLast方法,是在调用onComplete之前统一判断的,如果没有调用onComplete,是无法取得数据的;
//取得1,2
Observable.just(1, 2, 3, 4).take(2);
//取得3,4
Observable.just(1, 2, 3, 4).takeLast(2);
//取得10,11,12
Observable.intervalRange(10, 5, 0, 1, TimeUnit.SECONDS)
.take(3, TimeUnit.SECONDS);
//取得12,13,14,且取得的时间是相差无几的,而不是如上面的take有定时间隔
Observable.intervalRange(10, 5, 0, 1, TimeUnit.SECONDS)
.takeLast(3, TimeUnit.SECONDS);
//取得1,2,3
Observable.just(1, 2, 3, 4).takeUntil(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) throws Exception {
return integer > 2;
}
});
//取得1,2
Observable.just(1, 2, 3, 4).takeWhile(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) throws Exception {
return integer < 3;
}
})
skip有一系列跳过数据的方法,和take方法对应;
public final Observable<T> skip(long count)
public final Observable<T> skip(long time, TimeUnit unit)
public final Observable<T> skipLast(int count)
public final Observable<T> skipLast(long time, TimeUnit unit)
public final Observable<T> skipWhile(Predicate<? super T> predicate)
//取得3,4
Observable.just(1, 2, 3, 4).skip(2);
//取得1,2
Observable.just(1, 2, 3, 4).skipLast(2);
//取得13,14
Observable.intervalRange(10, 5, 0, 1, TimeUnit.SECONDS)
.skip(3, TimeUnit.SECONDS);
//取得10,11
Observable.intervalRange(10, 5, 0, 1, TimeUnit.SECONDS)
.skipLast(3, TimeUnit.SECONDS);
//取得3,4
Observable.just(1, 2, 3, 4).skipWhile(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) throws Exception {
return integer < 3;
}
})
sample/debounce/throttleFirst
用于在某个时间范围采样取得或过滤忽略某些数据。
sample用于取出某个时间段内最后发送出的数据;
throttleLast内部使用的sample,与其等价;
public final Observable<T> sample(long period, TimeUnit unit)
Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(ObservableEmitter<Long> observableEmitter) throws Exception {
observableEmitter.onNext(1L);
TimeUnit.MILLISECONDS.sleep(300);
observableEmitter.onNext(2L);
//此时在400ms内发送了第2个数据,这就是这个区间最后的数据了,为2
TimeUnit.MILLISECONDS.sleep(300);
observableEmitter.onNext(3L);
//此时已过600ms,处于第2个400ms区间内,只有3
TimeUnit.MILLISECONDS.sleep(500);
observableEmitter.onNext(4L);
//此时已过1100ms,处于第3个400ms区间内,只有4
TimeUnit.MILLISECONDS.sleep(500);
//此时已过1600ms,处于第4个400ms区间内,没有数据发送
observableEmitter.onNext(5L);
TimeUnit.MILLISECONDS.sleep(200);
observableEmitter.onNext(6L);
//此时已经过1800ms,处于第5个区间内,只有6
TimeUnit.MILLISECONDS.sleep(500);
observableEmitter.onComplete();
}
}).sample(400, TimeUnit.MILLISECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
System.out.println(aLong);
}
});
输出为:
2
3
4
6
debounce用于过滤掉某个时间段发送频繁的数据,常用于”防抖“,只要能够成功发送出数据(被订阅者接收),则重新计算时间;
throttleWithTimeout内部使用的debounce,与其等价;
public final Observable<T> debounce(long timeout, TimeUnit unit)
Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(ObservableEmitter<Long> observableEmitter) throws Exception {
observableEmitter.onNext(1L);
TimeUnit.MILLISECONDS.sleep(300);//过滤
observableEmitter.onNext(2L);
TimeUnit.MILLISECONDS.sleep(300);//过滤
observableEmitter.onNext(3L);
TimeUnit.MILLISECONDS.sleep(500);//已经超过400ms,发送出去,重新计时
observableEmitter.onNext(4L);
TimeUnit.MILLISECONDS.sleep(500);//已经超过400ms,发送出去,重新计时
observableEmitter.onNext(5L);
TimeUnit.MILLISECONDS.sleep(200);//过滤
observableEmitter.onNext(6L);
TimeUnit.MILLISECONDS.sleep(500);//已经超过400ms,发送出去,重新计时
observableEmitter.onComplete();
}
}).debounce(400, TimeUnit.MILLISECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
System.out.println(aLong);
}
});
输出为:
3
4
6
throttleFirst和sample原理类似,不同的是要取得某个时间段内的第1个数据,而非最后一个数据;
public final Observable<T> throttleFirst(long windowDuration, TimeUnit unit)
Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(ObservableEmitter<Long> observableEmitter) throws Exception {
//此时在第1个区间内,为1
observableEmitter.onNext(1L);
TimeUnit.MILLISECONDS.sleep(300);
observableEmitter.onNext(2L);
TimeUnit.MILLISECONDS.sleep(300);
observableEmitter.onNext(3L);
//此时在第2个区间内,接下来有500ms,会到第3个区间,这个区间的第1个数据只有3
TimeUnit.MILLISECONDS.sleep(500);
observableEmitter.onNext(4L);
//此时已过1100ms,处于第3个400ms区间内,只有4
TimeUnit.MILLISECONDS.sleep(500);
//此时已过1600ms,处于第4个400ms区间内,没有数据发送
observableEmitter.onNext(5L);
TimeUnit.MILLISECONDS.sleep(200);
//第5个区间刚开始就发送了5
observableEmitter.onNext(6L);
TimeUnit.MILLISECONDS.sleep(500);
observableEmitter.onComplete();
}
}).throttleFirst(400, TimeUnit.MILLISECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
System.out.println(aLong);
}
});
输出为:
1
3
4
5