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 <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

一些示例代码

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值