上一篇学完了Observable和Observer,这一篇学一下map操作符和flatMap操作符
1.先看一下map操作符:
map是RxJava中最简单的一个变换操作符了,map操作符的作用是将上游(Observable)发送的每一个事件,转换成一个函数,使得每一个上游发送的事件都按照指定的规则去做。
下面先看一个例子:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
Log.d("----", "subscribe: 发送的信息:"+1);
e.onNext(1);
Log.d("----", "subscribe: 发送的信息:"+2);
e.onNext(2);
Log.d("----", "subscribe: 发送的信息:"+3);
e.onNext(3);
Log.d("----", "subscribe: 完成");
e.onComplete();
}
}).map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
//map的作用就是转化,这里将int类型的数据 转换为 String类型的数据
return "this is " + integer;
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("----", "accept: 接收到的信息:"+s);
}
});
在上游我们发送的是数字类型, 而在下游我们接收的是String类型, 中间起转换作用的就是map操作符
看一下Log输出:
02-05 16:19:06.549 14418-14418/com.ckw.rxjava2demo D/----: subscribe: 发送的信息:1
02-05 16:19:06.549 14418-14418/com.ckw.rxjava2demo D/----: accept: 接收到的信息:this is 1
02-05 16:19:06.549 14418-14418/com.ckw.rxjava2demo D/----: subscribe: 发送的信息:2
02-05 16:19:06.549 14418-14418/com.ckw.rxjava2demo D/----: accept: 接收到的信息:this is 2
02-05 16:19:06.550 14418-14418/com.ckw.rxjava2demo D/----: subscribe: 发送的信息:3
02-05 16:19:06.550 14418-14418/com.ckw.rxjava2demo D/----: accept: 接收到的信息:this is 3
02-05 16:19:06.550 14418-14418/com.ckw.rxjava2demo D/----: subscribe: 完成
从log信息中我们可以看到,上游发送的是Int类型的数据,通过map操作符,转成了String。
接着看flatMap:
FlatMap将一个发送事件的上游Observable变换为多个发送事件的Observables,然后将它们发射的事件合并后放进一个单独的Observable里.
上游每发送一个事件, flatMap都将创建一个新的水管, 然后发送转换之后的新的事件,
下游接收到的就是这些新的水管发送的数据. 这里需要注意的是, flatMap并不保证事件的顺序
看一下例子:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
Log.d("----", "subscribe: 上游发送:1");
e.onNext(1);
Log.d("----", "subscribe: 上游发送:2");
e.onNext(2);
Log.d("----", "subscribe: 上游发送:3");
e.onNext(3);
Log.d("----", "subscribe: 上游发送完毕");
e.onComplete();
}
}).flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
List<String> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("this is "+integer);
}
return Observable.fromIterable(list).delay(10,TimeUnit.MILLISECONDS);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d("----", "accept: 接收到的信息:"+s);
}
});
Observable.fromIterable:
此方法接收一个继承自Iterable接口的参数,简单的说就是java中的集合类。因此你可以传入一个list集合等等
看一下Log输出:
02-05 16:23:29.263 15724-15724/com.ckw.rxjava2demo D/----: subscribe: 上游发送:1
02-05 16:23:29.281 15724-15724/com.ckw.rxjava2demo D/----: subscribe: 上游发送:2
02-05 16:23:29.282 15724-15724/com.ckw.rxjava2demo D/----: subscribe: 上游发送:3
02-05 16:23:29.283 15724-15724/com.ckw.rxjava2demo D/----: subscribe: 上游发送完毕
02-05 16:23:29.291 15724-15772/com.ckw.rxjava2demo D/----: accept: 接收到的信息:this is 1
02-05 16:23:29.292 15724-15773/com.ckw.rxjava2demo D/----: accept: 接收到的信息:this is 2
02-05 16:23:29.292 15724-15774/com.ckw.rxjava2demo D/----: accept: 接收到的信息:this is 3
3.模拟注册登录:
使用FlatMap模拟用户先注册,注册成功后直接登录的功能:
final Api api = create().create(Api.class);
// //之前有说过,只能subscribeOn一次,可以observeOn多次
api.register("ckw")//发起注册请求
.subscribeOn(Schedulers.io())//在io线程发起网络请求
.observeOn(AndroidSchedulers.mainThread())//在主线程处理注册请求结果
.doOnNext(new Consumer() {//感觉不是必须的,如果不用处理注册结果,就不需要了吧
@Override
public void accept(String s) throws Exception {
//先对注册的结果进行一些处理,这步不是必须的
}
})
.observeOn(Schedulers.io())//在io线程处理登录请求
.flatMap(new Function>() {
@Override
public ObservableSource apply(String s) throws Exception {
//发起登录的网络请求
return api.login("ckw");
}
})
.observeOn(AndroidSchedulers.mainThread())//在主线程处理登录请求结果
.subscribe(new Consumer() {
@Override
public void accept(String s) throws Exception {
Log.d("----", "accept: 登录成功");
}
}, new Consumer() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.d("----", "accept: 登录失败");
}
});
在这里我的返回值都是String,只是一个模拟的效果,实际上还是要根据自己的需求,创建数据类。
这是模拟的返回Retrofit的方法
private static Retrofit create() {
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
builder.readTimeout(10, TimeUnit.SECONDS);
builder.connectTimeout(9, TimeUnit.SECONDS);
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addInterceptor(interceptor);
}
return new Retrofit.Builder().baseUrl( "http://10.71.33.67:80")
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}