RxJava2常用的操作符

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  Observable 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  Observable 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  Observable fromIterable(Iterable source)
        String[] strings = {"aa12", "bb34", "cc56"};
        List<String> listString = Arrays.asList(strings);
        Observable.fromIterable(listString);

range用于快速发送多个整数,count为发送的数量而非终止范围;

public static Observable range(int start, int count) 
public static Observable 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 interval(long period, TimeUnit unit)
public static Observable interval(long initialDelay, long period, TimeUnit unit)
public static Observable 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 timer(long delay, TimeUnit unit)
		//延时3秒后,发送一个整数0
        Observable.timer(3, TimeUnit.SECONDS);

delay用于延时发送,区别在于delay产生泛型Observable,要使用于已经生成的Observable才能起作用;

public final Observable 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  Observable map(Function 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 scan(BiFunction 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  Observable flatMap(Function> mapper)
public final  Observable concatMap(Function> 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  Observable merge(Iterable> sources)
public static  Observable merge(ObservableSource source1, ObservableSource source2)

concat与merge类似,不过内部使用的concatMap,因此可以保证顺序;

public static  Observable concat(Iterable> 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  Observable zip(ObservableSource source1, ObservableSource source2, BiFunction zipper)

public static  Observable zipIterable(Iterable> sources, Function zipper, boolean delayError, int bufferSize)

public static  Observable zipArray(Function 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 filter(Predicate 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 distinct()
public final  Observable distinct(Function keySelector)

public final Observable distinctUntilChanged()
public final  Observable distinctUntilChanged(Function keySelector)
public final Observable distinctUntilChanged(BiPredicate 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 take(long count)
public final Observable take(long time, TimeUnit unit)

public final Observable takeLast(int count)
public final Observable takeLast(long count, long time, TimeUnit unit)

public final Observable takeUntil(Predicate stopPredicate)
public final Observable takeWhile(Predicate 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 skip(long count)
public final Observable skip(long time, TimeUnit unit)

public final Observable skipLast(int count)
public final Observable skipLast(long time, TimeUnit unit)

public final Observable skipWhile(Predicate 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 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 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 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

一些示例代码

你可能感兴趣的:(Java)