RxJava笔记3:操作符

简述

上篇博文中我们提到了map 操作符,它与Kotlin中的map函数作用类似,对上游的每个事件都执行该方法中的逻辑,改变原始数据,这里的每个事件不包含 onComplete 和 onError,是有数据的事件(onNext,onSuccess)。RxJava中还提供了其他丰富的操作符,满足各种需求。

创建相关

just创建一个可观察源,将参数依此发布出去

Observable.just(1,2,3,4)
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer Integer) throws Exception {
                System.out.println("onNext " + Integer);
            }
        });

from 与just一样, just其实就是调用的from相应的方法

ArrayList<Object> objects = new ArrayList<>();
objects.add(0); objects.add(1);
Observable.fromIterable(objects).subscribe(new Consumer<Object>() {
    @Override
    public void accept(Object o) throws Exception {
        System.out.println("onNext " + o);
    }
});
System.out: onNext 0
System.out: onNext 1

range创建一个可观察源,从给定的起始值开始,发送给定次数的事件,数值递增

Observable.range(10,3)//起始值10 ,递增发送3个
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer i) throws Exception {
                System.out.println("onNext " + i);
            }
        });
        
System.out: onNext 10
System.out: onNext 11
System.out: onNext 12

interval创建一个可观察源,间隔一段时间发布一个事件

Observable.interval(1, TimeUnit.S) // 间隔1秒发布一个事件
        .subscribe(new Consumer<Long>() {
            @Override
            public void accept(Long aLong) throws Exception {
                System.out.println("onNext " + aLong);
            }
        });
System.out: onNext 0 //初始值是从0开始
System.out: onNext 1
System.out: onNext 2
System.out: onNext 3
System.out: onNext 4

intervalRange 是 interval 和 Range 的结合

//初始值是2,发送2次,延时10秒后开始发送,发送间隔1秒
Observable.intervalRange(2L, 3L, 10L, 2L, TimeUnit.SECONDS)
        .subscribe(new Consumer<Long>() {
            @Override
            public void accept(Long aLong) throws Exception {
                System.out.println("onNext " + aLong);
            }
        });
System.out: onNext 2
System.out: onNext 3
System.out: onNext 4        

map相关

flatMap对上游的每个事件(onNext 或 onSuccess)都应用该函数,返回一个新的可观察源。

Observable.create(new ObservableOnSubscribe<Integer>() {
    @Override
    public void subscribe(ObservableEmitter<Integer> e) throws Exception {
        e.onNext(1);
        e.onNext(2);
        e.onComplete();
    }
}).subscribeOn(Schedulers.newThread()).observeOn(Schedulers.newThread())
        .flatMap(new Function<Integer, ObservableSource<String>>() {
            @Override
            public ObservableSource<String> apply(Integer i) throws Exception {
                return Observable.just("A" + i, "A" + i); // 标记 1
            }
        })
        .subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                System.out.println("onNext " + s);
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                System.out.println("onError ");
            }
        }, new Action() {
            @Override
            public void run() throws Exception {
                System.out.println("onComplete ");
            }
        });
        
System.out: onNext A1
System.out: onNext A1
System.out: onNext A2
System.out: onNext A2
System.out: onComplete         

flatMap的执行线程可以通过ObserveOn指定,如果没有指定,和它的上游线程一样。

flatMap在实际开发中很有用,比如常见的,app登入成功拿到token后,去获取数据。看下面伪代码:

@POST("login")
Maybe<LoginData> login(@Query("account") String account, @Query("password") String password);

@GET("getData")
Maybe<Data> getData(@Query("token") String token)

RetrofitClient.api.login("account","123456")
        .subscribeOn(Schedulers.newThread())
        .flatMap(new Function<LoginData, MaybeSource<Data>>() {
            @Override
            public MaybeSource<Data> apply(LoginData loginData) throws Exception {
            	//登入成功获取数据
                return RetrofitClient.api.getData(loginData.getToken())
            }
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer<Data>() {
            @Override
            public void accept(Data data) throws Exception {
                //获取数据成功
            }
        });

看到没,flatMap让我们的代码更加整洁优雅,不用写很多嵌套的。这里的Maybe和Observable类似,也是一个可观察源,后面的文章会介绍。

concatMap 和 flatMap 有同样的功能,和同样的用法,只不过concatMap能保证事件的顺序。

Observable.range(1, 5)
        .subscribeOn(Schedulers.newThread()).observeOn(Schedulers.newThread())
        .flatMap(new Function<Integer, ObservableSource<String>>() {
            @Override
            public ObservableSource<String> apply(Integer i) throws Exception {
            	//延时500毫秒发布事件
                return Observable.just("A" + i).delay(500, TimeUnit.MILLISECONDS);
            }
        })
        .subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                System.out.println("onNext " + s);
            }
        });
        
System.out: onNext A1
System.out: onNext A2
System.out: onNext A4
System.out: onNext A3
System.out: onNext A5        

可以看到输出的顺序和事件发布的顺序不一致,将 flatMap 改成 concatMap 之后,顺序就一样了。

Observable.range(1, 5)
        .subscribeOn(Schedulers.newThread()).observeOn(Schedulers.newThread())
        .concatMap(new Function<Integer, ObservableSource<String>>() {
            @Override
            public ObservableSource<String> apply(Integer i) throws Exception {
                return Observable.just("A" + i).delay(500, TimeUnit.MILLISECONDS);
            }
        })
        .subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                System.out.println("onNext " + s);
            }
        });
        
System.out: onNext A1
System.out: onNext A2
System.out: onNext A3
System.out: onNext A4
System.out: onNext A5

switchMap 与 flatMap 类似,当上游发送新的事件时,如果 switchMap 还有旧的事件没处理时,就会不处理旧的事件,直接处理新的事件。

Observable.just(1, 2, 3, 4, 5)
        .switchMap(new Function<Integer, ObservableSource<Integer>>() {
            @Override
            public ObservableSource<Integer> apply(Integer integer) throws Exception {
                //切换到新的线程处理事件,上面发送5时,这里可能还没有发布 1 ,就会取消掉处理旧的
                return Observable.just(integer).subscribeOn(Schedulers.io());
            }
        })
        .observeOn(Schedulers.io())
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println("onNext " + integer);
            }
        });
        
System.out: onNext 5

组合

zip 将多个可观察源的事件一对一组合,然后发布给下游。组合的事件数量与发布事件个数最少的那个可观察源相同。

Observable.zip(Observable.just(1, 2, 3), Observable.just("A", "B"),
        new BiFunction<Integer, String , Object>() {
            @Override
            public Object apply(Integer i, String s) throws Exception {
                return "i " + i + " s " + s;
            }
        })
        .subscribe(new Consumer<Object>() {
            @Override
            public void accept(Object o) throws Exception {
                System.out.println("onNext " + o);
            }
        });
        
System.out: onNext i 1 s A
System.out: onNext i 2 s B

mergeWith 将可观察源合并起来,等全部可观察源都发送 onComplete 事件后,下游才能收到 onComplete 事件。

Observable.just(1, 2, 3)
        .mergeWith(Observable.just(4))
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println("onNext " + integer);
            }
        });
System.out: onNext 1
System.out: onNext 2
System.out: onNext 3
System.out: onNext 4

事件相关

delaySubscription 延迟订阅

Observable.just(1, 2, 3)
        .delaySubscription(2, TimeUnit.SECONDS)// 延迟2秒订阅
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println("onNext " + integer);
            }
        });

delay 延迟发射事件

Observable.just(1, 2, 3)
        .delay(2, TimeUnit.SECONDS)// 延迟2秒后开始发射事件
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println("onNext " + integer);
            }
        });

timeInterval 拦截上游的事件,将事件的间隔和数据返回给下游

Observable.create(new ObservableOnSubscribe<Object>() {
    @Override
    public void subscribe(ObservableEmitter<Object> e) throws Exception {
        e.onNext(1);
        Thread.sleep(1000);
        e.onNext(2);
        Thread.sleep(500);
        e.onNext(3);
    }
}).timeInterval().subscribe(new Consumer<Timed<Object>>() {
            @Override
            public void accept(Timed<Object> objectTimed) throws Exception {
                System.out.println(objectTimed);
            }
        });
        
System.out: Timed[time=0, unit=MILLISECONDS, value=1]
System.out: Timed[time=1001, unit=MILLISECONDS, value=2]
System.out: Timed[time=500, unit=MILLISECONDS, value=3]

timestamp 与 timeInterval 一样,区别是timestamp的time是时间戳,不是时间间隔。

timeout 超过指定的时间,事件还没有发布完成,如果有设置超时回调,就执行回调,没有就会执行onError,报超时异常。这里的回调也是一个可观察源

Observable.create(new ObservableOnSubscribe<Integer>() {
    @Override
    public void subscribe(ObservableEmitter<Integer> e) throws Exception {
        e.onNext(1);
        Thread.sleep(1000);
        e.onNext(2);
        Thread.sleep(500);
        e.onNext(3);
    }
}).timeout(1, TimeUnit.SECONDS, Observable.create(new ObservableOnSubscribe<Integer>() {
    @Override
    public void subscribe(ObservableEmitter<Integer> e) throws Exception {
        System.out.println("timeout ");
        e.onNext(222);//如果超时了,会发送这个事件
    }
})).subscribe(new Consumer<Integer>() {
    @Override
    public void accept(Integer o) throws Exception {
        System.out.println("onNext " + o);
    }
}, new Consumer<Throwable>() {
    @Override
    public void accept(Throwable throwable) throws Exception {
        System.out.println("onNext " + throwable);
    }
});
System.out: onNext 1
System.out: timeout 
System.out: onNext 222

doFinally 注册一个回调,在 onComplete、onSuccess、onError、超时、取消订阅这些事件发生后,执行该回调,和 try finally 机制类似。doOnNext,doOnComplete,doOnError,doOnSuccess 也是类似注册一个回调,在对应事件发生后回调。
doOnDispose注册一个回调,在取消订阅这些事件发生后,执行该回调。
这些do方法执行在对应事件发生的线程。

Observable.just(1, 2, 3)
        .doFinally(new Action() {
            @Override
            public void run() throws Exception {
                System.out.println("doFinally ");
            }
        })
        .doOnDispose(new Action() {
            @Override
            public void run() throws Exception {
                System.out.println("doOnDispose ");
            }
        })
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer Integer) throws Exception {
                System.out.println("onNext " + Integer);
            }
        });
System.out: onNext 1
System.out: onNext 2
System.out: onNext 3
System.out: doFinally 

过滤相关

throttleFirst 在给定时间窗口内,只取第一个事件。

Observable.just(1, 2, 3, 4, 5)
        .throttleFirst(1, TimeUnit.SECONDS)
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println("onNext " + integer);
            }
        }); 
System.out: onNext 1

debounce 如果一个事件是给定的时间内的最后一个事件,则发送该事件。

Observable.just(1, 2, 3, 4, 5)
        .debounce(1, TimeUnit.SECONDS)
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println("onNext " + integer);
            }
        });
System.out: onNext 5

throttleFirst 和 debounce 都可以做 Button 的点击事件防抖。

sample 采样,与 debounce 类似 ,在给定时间窗口内,只取最近的事件

distinct 过滤掉相同数值的事件,比较的应该是toString的值。

Pair<String, Float> pair1 = new Pair<>("A", 1.2f);
Pair<String, Float> pair2 = new Pair<>("A", 1.2f);
Observable.create(new ObservableOnSubscribe<Pair<String, Float>>() {
    @Override
    public void subscribe(ObservableEmitter<Pair<String, Float>> e) throws Exception {
        e.onNext(pair1);
        e.onNext(pair2);
    }
}).distinct()
        .subscribe(new Consumer<Pair<String, Float>>() {
            @Override
            public void accept(Pair<String, Float> s) throws Exception {
                System.out.println("onNext " + s);
            }
        });
        
System.out: onNext Pair{A 1.2}

distinctUntilChanged() 过滤掉连续重复的数据。

first 只发射第一项数据。
last 只发射最后的一项数据。

skip 跳过开始的多少个事件。
skipLast 跳过最后的多少个事件。

elementAt 发射第几个事件。
elementAtOrDefault 发射第几个事件,如果可观察源事件少于这个数就发射默认值。

filter过滤出满足的条件事件

Observable.just(1, 2, 3, 4, 5, 6, 7, 8)
        .filter(new Predicate<Integer>() {
            @Override
            public boolean test(Integer i) throws Exception {
                return i > 6;//过滤出大于6的事件
            }
        })
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer i) throws Exception {
                System.out.println("onNext " + i);
            }
        });
        
System.out: onNext 7
System.out: onNext 8

take 只接受指定数量的事件,从第一个事件开始数

Observable.range(1, 20)
        .take(3)
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println("onNext " + integer);
            }
        });
System.out: onNext 1
System.out: onNext 2
System.out: onNext 3

takeLast 只接受指定数量的事件,从最后一个事件开始数

Observable.range(1, 20)
        .takeLast(4)
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println("onNext " + integer);
            }
        });
System.out: onNext 17
System.out: onNext 18
System.out: onNext 19
System.out: onNext 20

takeUntil 满足什么条件时,停止接受事件

Observable.range(1, 20)
        .takeUntil(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) throws Exception {
                return integer == 3;// 在  integer == 3 时,不在接受事件
            }
        })
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println("onNext " + integer);
            }
        });
System.out: onNext 1
System.out: onNext 2
System.out: onNext 3

takeWhile 不满足什么条件时,停止接受事件

Observable.range(1, 20)
        .takeWhile(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) throws Exception {
                return integer <= 2;// integer 大于2之后就停止接受事件
            }
        })
        .subscribe(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                System.out.println("onNext " + integer);
            }
        });
System.out: onNext 1
System.out: onNext 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值