RxJava是基于观察者模式设计的,它提供了一种响应式编程的思维方式,使得异步编程更加灵活和高效。链式操作避免了多层嵌套,使代码更加清晰简
RxJava 的主要成员角色 - 被观察者 / 观察者 / 订阅 / 操作符
Observable(被观察者): Observable 是一个 可以发送消息的数据源。
Observer(观察者): Observer 表示一个接收 Observable 发送消息的观察者。 它可以处理从 Observable 发射的消息, 还可以处理onNext、onError、onComplete的事件。
Subscription(订阅): 订阅是 Observer 对 Observable 的绑定。
Operator(操作符): 用于处理和转换 Observable发送的消息。可以进行消息的 过滤(filter\take)、变换(map/flatMap)、组合(contact/merge/zip)等操作 ;
Rxjava常用操作符
-
filter() 操作符:过滤流中的元素,只保留符合条件的。
-
take() 操作符:从流中取前 n 个元素。
-
map() 操作符:将流中的每个元素通过函数转换为另一个元素。
-
flatMap() 操作符:将流中的每个元素通过函数转换为多个元素,并将这些组合成一个新的流。
-
reduce() 操作符:将流中的元素通过函数进行累加,得到一个最终结果。
-
scan() 操作符:将流中的元素通过函数进行累加,得到每一步的中间结果。
-
concat() 操作符:将多个流组合成新的流。
-
merge() 操作符:将多个流合并成新的流。
-
zip() 操作符:将多个流中的元素按顺序一一组合成新的元素,并形成新的流。
-
debounce() 操作符:过滤流中发射过快的元素,只保留一个元素。
map和flatMap有什么区别
- map 和 flatMap 都可以用来对数据流中的数据进行变换。
- map 只进行一次变换,并将变换后的结果发射出去.
- flatMap 进行多次变换,并将得到的 Observable 合并成一个新的 Observable 发射出去
背压定义
背压(Backpressure)是指当数据产生速度大于消费速度,程序处理不过来就会出现堆积。导致内存溢出、程序崩溃等问题。
背压改进办法
- 生产者数量=消费者数量
- 节流,丢弃一部分请求
- 打包,把所有事件封装在一个集合中发送
Rxjava1.x提供了onBackpressureBuffer(time)、onBackpressureDrop() 等)来缓解背压问题,但这只是对数据流进行了缓存或者丢弃处理。
RxJava 2.0后 引入了新的数据类型 Flowable,提供了更多的背压控制策略。
- onBackpressureBuffer 策略会在内存中缓存数据,直到消费者可以消费这些数据;
- onBackpressureDrop 策略会在数据流中丢弃一部分数据,直到消费者可以消费;
- onBackpressureLatest 策略会只保留最新的数据,丢弃旧数据
操作符实例
1、skip(跳过)
可以作用于Flowable,Observable,表示源发射数据前,跳过多少个
Observable<Integer> source = Observable.just(1, 2, 3, 4, 5, 6);
source.skip(3)
.subscribe(System.out::print);
打印结果:456
Observable<Integer> source = Observable.just(1, 2, 3, 4, 5, 6);
//skipLast(n)操作表示从流的尾部跳过n个元素。
source.skipLast(4)
.subscribe(System.out::print);
打印结果:1 2
2、debounce(去抖动)
通常为了防止用户重复点击而设置标记位,在规定时间内,用户重复点击只有最后一次有效,
Observable<String> source = Observable.create(emitter -> {
emitter.onNext("你");
Thread.sleep(1100);
emitter.onNext("真");
Thread.sleep(500);
emitter.onNext("的");
Thread.sleep(450);
emitter.onNext("漂");
Thread.sleep(2000);
emitter.onNext("亮");
emitter.onComplete();
});
source.subscribeOn(Schedulers.io())
.debounce(1, TimeUnit.SECONDS)
.blockingSubscribe(
item -> System.out.print(item+" "),
Throwable::printStackTrace,
() -> System.out.println("onComplete"));
打印:你 漂 亮 onComplete
解析:操作符debounce的时间设为1秒,发送A后1.1秒并没有发射其他数据,所以"你"能成功发射。
发射"真"后,在1秒之内,又发射了"的"和"漂",在"漂"之后的2秒才发射"亮",
所以"真"、"的"都失效,只有"漂"有效;而"亮"之后已经没有其他数据流了,所有"亮"有效。
3、distinct(去重)
可作用于Flowable,Observable,去掉数据源重复的数据。
Observable.just(2, 4, 4, 2, 1)
.distinct()
.subscribe(System.out::print);
打印: 2 4 1
Observable.just(1, 1, 2, 1, 2, 3, 3)
.distinctUntilChanged()//去掉相邻重复数据
.subscribe(System.out::print);
打印:1 2 1 2 3
4、elementAt(获取指定位置元素)
可作用于Flowable,Observable,从数据源获取指定位置的元素,从0开始。
Observable.just(6,4,3,1,5,8)
.elementAt(0)
.subscribe(integer ->
Log.d("TAG","elmentAt->"+integer));
打印:6
Observable<String> source = Observable.just("A", "B", "C", "D");
//指定元素的位置超过数据长度,则发射异常
Single<String> element = source.elementAtOrError(4);
element.subscribe(
name -> System.out.println("name"),
error -> System.out.println("onError: " + error));
打印:name
5、filter(过滤)
可作用于 Flowable,Observable,Maybe,Single。在filter中返回表示发射该元素,返回false表示过滤该数据。
Observable.just(1, 2, 3, 4, 5)
.filter(x -> x % 2 == 0)
.subscribe(System.out::print);
打印:2 4
6、first(第一个)
作用于 Flowable,Observable。发射数据源第一个数据,如果没有则发送默认值。
Observable<String> source = Observable.just("a", "b", "c");
Single<String> firstOrDefault = source.first("d");
firstOrDefault.subscribe(System.out::println);
打印:a
Observable<String> emptySource = Observable.empty();
Single<String> firstOrError = emptySource.firstOrError();
firstOrError.subscribe(
element -> System.out.println("element"),
error -> System.out.println("onError: " + error));
打印:onError: java.util.NoSuchElementException
first返回的是Single,firstOrError在没有数据会返回异常
7、last(最后一个)
last、lastElement、lastOrError与fist、firstElement、firstOrError相对应。
Observable<String> source = Observable.just("a", "b", "c");
Single<String> lastOrDefault = source.last("d");
lastOrDefault.subscribe(System.out::println);
打印:c
Observable<String> source = Observable.just("a", "b", "c");
Maybe<String> last = source.lastElement();
last.subscribe(System.out::println);
打印:c
Observable<String> emptySource = Observable.empty();
Single<String> lastOrError = emptySource.lastOrError();
lastOrError.subscribe(
element -> System.out.println("element"),
error -> System.out.println("onError: " + error));
打印:onError: java.util.NoSuchElementException
8、ignoreElements & ignoreElement(忽略元素)
ignoreElements 作用于Flowable、Observable。
ignoreElement 作用于Maybe、Single。两者都是忽略掉数据,返回完成或者错误时间。
Single<Long> source = Single.timer(1, TimeUnit.SECONDS);
Completable completable = source.ignoreElement();
completable.doOnComplete(() -> System.out.println("Good!"))
.blockingAwait();
1秒后打印:Good!
Observable<Long> source = Observable.intervalRange(1, 5, 1, 1, TimeUnit.SECONDS);
Completable completable = source.ignoreElements();
completable.doOnComplete(() -> System.out.println("Good!"))
.blockingAwait();
5秒后打印:Good!
9、sample
作用于Flowable、Observable,在一个周期内发射最新的数据。
Observable<String> source = Observable.create(emitter -> {
emitter.onNext("A");
Thread.sleep(500);
emitter.onNext("B");
Thread.sleep(200);
emitter.onNext("C");
Thread.sleep(800);
emitter.onNext("D");
Thread.sleep(600);
emitter.onNext("E");
emitter.onComplete();
});
source.subscribeOn(Schedulers.io())
.sample(1, TimeUnit.SECONDS)
.blockingSubscribe(
item -> System.out.print(item+" "),
Throwable::printStackTrace,
() -> System.out.print("onComplete"));
// 打印: C D onComplete
sample是以时间为周期的发射,一秒又一秒内的最新数据。第1s内有A、B、C;第2s内只有D,第3s没到一个周期,所以E就丢弃
10、ofType
作用于Flowable、Observable、Maybe、过滤掉类型。
Observable<Number> numbers = Observable.just(1, 3, 2.71, 2f, 7f);
Observable<Integer> integers = numbers.ofType(Integer.class);
integers.subscribe((Integer x) -> System.out.print(x+" "));
打印:1 3
11、take & takeLast
作用于Flowable、Observable,take发射前n个元素;takeLast发射后n个元素。
Observable<Integer> source = Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
source.take(3)
.subscribe(System.out::print);
打印:1 2 3
source.takeLast(3)
.subscribe(System.out::println);
打印:8 9 10
12、startWith
可作用于Flowable、Observable。将指定数据源合并在另外数据源的开头。
Observable<String> names = Observable.just("A", "B");
Observable<String> otherNames = Observable.just("C", "D","8");
names.startWith(otherNames).subscribe(item -> Log.d(TAG,item));
打印:
C
D
8
A
B
13、merge
可作用所有数据源类型,用于合并多个数据源到一个数据源。
Observable<String> names = Observable.just("A", "B");
Observable<String> otherNames = Observable.just("C", "D","8");
Observable.merge(names,otherNames).subscribe(name -> Log.d(TAG,name));
//或者
//names.mergeWith(otherNames).subscribe(name -> Log.d(TAG,name));
打印:
A
B
C
D
8
14、zip
可作用于Flowable、Observable、Maybe、Single。将多个数据源的数据一个一个的合并在一起哇。当其中一个数据源发射完事件之后,若其他数据源还有数据未发射完毕,也会停止。
Observable<String> names = Observable.just("A", "B");
Observable<String> otherNames = Observable.just("C", "D", "8");
names.zipWith(otherNames, (first, last) -> first + "-" + last)
.subscribe(item -> Log.d(TAG, item));
打印:
A-C
B-D
15、buffer
作用于Flowable、Observable。指将数据源拆解含有长度为n的list的多个数据源,不够n的成为一个数据源。
Observable.range(0, 10)
.buffer(3)
.subscribe((List<Integer> buffer) -> System.out.println(buffer));
打印:
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9]
16、cast
作用于Flowable、Observable、Maybe、Single。将数据元素转型成其他类型,转型失败会抛出异常。
Observable<Number> numbers = Observable.just(1, 2.0, 3f, 4);
numbers.filter((Number x) -> Integer.class.isInstance(x))
.cast(Integer.class)
.subscribe((Integer x) -> System.out.println(x));
打印:
1
4
16、concatMap
作用于Flowable、Observable、Maybe。将数据源的元素作用于指定函数后,将函数的返回值有序的存在新的数据源。
Observable.range(0, 5)
.concatMap(i -> {
long delay = Math.round(Math.random() * 2);
return Observable.timer(delay, TimeUnit.SECONDS).map(n -> i);
})
.blockingSubscribe(System.out::print);
打印 01234
17、flatMap
作用于Flowable、Observable、Maybe、Single。与contactMap类似,只是contactMap的数据发射是有序的,而flatMap是无序的。
Observable.just("a", "b", "c")
.flatMap(a -> {
return Observable.intervalRange(1, 3, 0, 1, TimeUnit.SECONDS)
.map(b -> '(' + a + ", " + b + ')');
})
.blockingSubscribe(System.out::println);
打印:
(a, 1)
(c, 1)
(b, 1)
(a, 2)
(c, 2)
(b, 2)
(a, 3)
(c, 3)
(b, 3)
18、groupBy
作用于Flowable、Observable。根据一定的规则对数据源进行分组。
Observable<String> animals = Observable.just(
"aa", "bb", "cc", "ce", "fe", "fg", "bd", "ae");
animals.groupBy(animal -> animal.charAt(0), String::toUpperCase)
.concatMapSingle(Observable::toList)
.subscribe(System.out::println);
打印:
[AA, AE]
[BB,BD]
[CC, CE]
[FE, FG]
19、window
对数据源发射出来的数据进行收集,按照指定的数量进行分组,以组的形式重新发射。
Observable.range(1, 6)
.window(2)
.flatMapSingle(window -> {
return window.map(String::valueOf)
.reduce(new StringJoiner(", ", "[", "]"), StringJoiner::add);
})
.subscribe(System.out::println);
打印:
[1, 2]
[3, 4]
[5, 6]
20、timeout(超时)
作用于Flowable、Observable、Maybe、Single、Completabl。后一个数据发射未在前一个元素发射后规定时间内发射则返回超时异常。
Observable<String> source = Observable.create(emitter -> {
emitter.onNext("A");
Thread.sleep(800);
emitter.onNext("B");
Thread.sleep(400);
emitter.onNext("C");
Thread.sleep(1200);
emitter.onNext("D");
emitter.onComplete();
});
source.timeout(1, TimeUnit.SECONDS)
.subscribe(
item -> System.out.println("onNext: " + item),
error -> System.out.println("onError: " + error),
() -> System.out.println("Done!"));
打印:
onNext: A
onNext: B
onNext: C
onError: java.util.concurrent.TimeoutException:
The source did not signal an event for 1 seconds
and has been terminated.