flatMap,zip,Merge区别
flatMap
嵌套请求->多用于一个接口的请求依赖另一个API请求返回的数据
//例如:先登录获取token后,再去请求另一个接口
Observable<AuthModel> login = EasyHttp.post(ComParamContact.Login.PATH)
.params(ComParamContact.Login.ACCOUNT, "18688994275")
.params(ComParamContact.Login.PASSWORD, MD5.encrypt4login("123456", AppConstant.APP_SECRET))
.sign(true)
.timeStamp(true).execute(AuthModel.class);
login.flatMap(new Function<AuthModel, ObservableSource<SkinTestResult>>() {
@Override
public ObservableSource<SkinTestResult> apply(@NonNull AuthModel authModel) throws Exception {
return EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")
.params("accessToken", authModel.getAccessToken())//这个地方只是举例,并不一定是需要accessToken
.timeStamp(true)
.execute(SkinTestResult.class);
}
}).subscribe(new ProgressSubscriber<SkinTestResult>(this, mProgressDialog) {
@Override
public void onError(ApiException e) {
super.onError(e);
showToast(e.getMessage());
}
@Override
public void onNext(SkinTestResult skinTestResult) {
showToast(skinTestResult.toString());
}
});
Zip
使用zip操作符合并等待多个网络请求完成后,再刷新界面
//例如下面:数据来自3个不同的接口
Observable<ResultBean> mobileObservable = EasyHttp.get("http://apis.juhe.cn/mobile/get")
.params("phone", "18688994275")
.params("dtype", "json")
.params("key", "5682c1f44a7f486e40f9720d6c97ffe4")
.execute(new CallClazzProxy<TestApiResult1<ResultBean>, ResultBean>(ResultBean.class) {
});
Observable<Content> searchObservable = EasyHttp.get("/ajax.php")
.baseUrl("http://fy.iciba.com")
.params("a", "fy")
.params("f", "auto")
.params("t", "auto")
.params("w", "hello world")
//采用代理
.execute(new CallClazzProxy<TestApiResult6<Content>, Content>(Content.class) {
});
Observable<List<SectionItem>> listObservable = EasyHttp.get("http://news-at.zhihu.com/api/3/sections")
.execute(new CallClazzProxy<TestApiResult5<List<SectionItem>>, List<SectionItem>>(new TypeToken<List<SectionItem>>() {
}.getType()) {
});
//new Function3最后一个参数这里用的是List<Object>,表示将3个返回的结果,放在同一个集合最终一次性返回,你也可以指定返回其它你需要的数据类型并不一定是List<Object>
//假如这三个接口返回的都是TestBean,那么就可以直接用具体的List<TestBean>,不需要用List<Object>
Observable.zip(mobileObservable, searchObservable, listObservable, new Function3<ResultBean, Content, List<SectionItem>, List<Object>>() {
@Override
public List<Object> apply(@NonNull ResultBean resultbean, @NonNull Content content, @NonNull List<SectionItem> sectionItems) throws Exception {
//将接收到的3个数据先暂存起来,一次性发给订阅者
List list = new ArrayList();
list.add(resultbean);
list.add(content);
list.add(sectionItems);
return list;
}
}).subscribe(new BaseSubscriber<List<Object>>() {
@Override
public void onError(ApiException e) {
showToast(e.getMessage());
}
@Override
public void onNext(@NonNull List<Object> objects) {
showToast(objects.toString());
}
});
Merge
//Merge其实只是将多个Obsevables的输出序列变为一个,方便订阅者统一处理,对于订阅者来说就仿佛只订阅了一个观察者一样。
//拼接两个/多个Observable的输出,不保证顺序,按照事件产生的顺序发送给订阅者
//这个请求故意延时5秒再发送-最后测试结果发现,并不是searchObservable等待mobileObservable5秒后再发送
Observable<ResultBean> mobileObservable = Observable.timer(5, TimeUnit.SECONDS).flatMap(new Function<Long, ObservableSource<ResultBean>>() {
@Override
public ObservableSource<ResultBean> apply(@NonNull Long aLong) throws Exception {
return EasyHttp.get("http://apis.juhe.cn/mobile/get")
.params("phone", "18688994275")
.params("dtype", "json")
.params("key", "5682c1f44a7f486e40f9720d6c97ffe4")
.execute(new CallClazzProxy<TestApiResult1<ResultBean>, ResultBean>(ResultBean.class) {
});
}
});
Observable<Content> searchObservable = EasyHttp.get("/ajax.php")
.baseUrl("http://fy.iciba.com")
.params("a", "fy")
.params("f", "auto")
.params("t", "auto")
.params("w", "hello world")
//采用代理
.execute(new CallClazzProxy<TestApiResult6<Content>, Content>(Content.class) {
});
//merge和mergeDelayError都是合并,但是需要注意二者区别。
//merge:合并的请求,如果有一个接口报错了,就立马报错,会终止整个流,另外的接口也不会请求。
//mergeDelayError:合并的请求,如果有一个接口报错了,会延迟错误处理,后面的接口会继续执行没有被中断。
//使用时根据需要选用merge/mergeDelayError
//Observable.merge(searchObservable,mobileObservable).subscribe(new BaseSubscriber<Object>() {
Observable.mergeDelayError(searchObservable, mobileObservable).subscribe(new BaseSubscriber<Object>() {
@Override
public void onError(ApiException e) {
showToast(e.getMessage());
}
@Override
public void onNext(@NonNull Object object) {
//为什么用Object接收,因为两个接口请求返回的数据类型不是一样的,如果是一样的就用具体的对象接收就可以了,
// 不再需要instanceof麻烦的判断
if (object instanceof ResultBean) {//mobileObservable 返回的结果
//处理 ResultBean逻辑
} else if (object instanceof Content) {
//处理 Content逻辑
}
showToast(object.toString());
}
});