上一节我们学习了创建操作符和from操作符,今天开始学习变换操作符,所谓变换,显然是将上游被观察者发送的数据进行变化后再发送给下游观察者。
Map 操作符
- 方法预览
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) { ...}
- 作用及特点
- 将被观察者发送的每一个事件都通过指定的 Funcion 对象的apply()方法进行处理转换
- 将之前的事件类型转换为另一种事件类型
- 通过map 操作符可以将被观察者发送的事件转换为任意类型的事件
- 举例:
- 需求:假如上游被观察者发送了一些整型的数字,如何将它们转换为字符串
在这里,通过map 操作符就可以轻松实现:
Observable.just(1,2,3,4)
.map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
return integer +"从 Integer变成了 String类型:"+integer;
}
}).subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
LogUtil.d(s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
运行结果如下:
Flatmap 操作符
在学习faltmap 操作符之前,我们来回忆一下,之前在学习线程调度的时候,当时在完成注册后自动登录功能的时候,我们用到了flatmap 操作符将用户注册的 Observable转换为了另一个登录的Observable并发送出去。
//1.创建retrofit对象注册
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://wanandroid.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
//创建请求接口对象
ApiService api = retrofit.create(ApiService.class);
//使用接口请求对象创建call对象
Observable<RegisterResp> call = api.register(username, password, repassword);
call.subscribeOn(Schedulers.io())
.flatMap(new Function<RegisterResp, ObservableSource<LoginResponse>>() {
@Override
public ObservableSource<LoginResponse> apply(RegisterResp registerResp) throws Exception {
if (-1==registerResp.getErrorCode()){
return Observable.error(new Throwable("用户名已经注册"));
}else if (-1001==registerResp.getErrorCode()){
return Observable.error(new Throwable("注册失败"));
}
return api.login(username, password);
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<LoginResponse>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(LoginResponse loginResponse) {
Toast.makeText(MainActivity.this, "恭喜你登录成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(Throwable e) {
if ("注册失败".equals(e.getMessage())){
Toast.makeText(MainActivity.this, "注册失败", Toast.LENGTH_SHORT).show();
}else if (("用户名已经注册".equals(e.getMessage()))){
Toast.makeText(MainActivity.this, "用户名已经注册", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onComplete() {
}
});
在上面的代码中,上游被观察者先到IO线程其发起注册的请求,然后通过faltmap 将注册信息后交给了负责登录的 被观察者,最终回到主线程去进行UI 的更新。
这个过程我们可以这么理解,我们将负责注册的被观察者记为 ObservableA,它负责发送注册的事件,它持有所有的注册信息,然后遇到faltmap操作符,经过这个操作符的处理,将之前负责发送数据的ObservableA交给了ObservableB,告诉ObservableA,接下来的事情统一交给我好了,你不用管了,然后ObservableB将这些事件打包发送了出去,开始进行登录的操作。
那么有人可能会问了,map和faltmap都是进行数据的处理和事件的转换,那到底有什么不一样,其实很简单,通过代码可以看出,在map操作符中,处理事件的 Function对象的apply()返回的是最终的数据类型,但是Observable并没有变,而flatMap操作符中,处理事件的 Function对象的apply()返回的是另一个Observable,什么意思?负责接下来发送数据的人变了,不再是以前那个发送者了。
所以,通过map操作符变换后的只是事件类型变了,而flatmap操作符处理则是直接将发送事件的Observable 换成了另一个。这也是它们最大不同。
需要注意的是,flatmap操作符处理后的事件是无序的 ,而如果想要使发送的事件有序,则使用concatMap 操作符处理即可。
RxJava2 学习教程已更新,详情可以移步查看