简述
上篇博文中我们提到了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