Rxjava - 链式可观察对象
Rxjava - chain observables
请看这段代码:
Disposable disposable = mcityService.authLogin(request,Utils.prepareHeaders())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(resp ->
{
mCompositeDisposable.add(mcityService.getUserDetails(selectedCity.id,Utils.prepareHeaders(resp.tokenType,resp.accessToken))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(userDetails ->
{
/*process resp and user details*/
}));
}, throwable ->
{
process errors
});
mCompositeDisposable.add(disposable);
}
所以基本上我需要调用authLogin
,如果成功,调用getUserDetails
(需要authLogin
调用结果中的一些字段),如果getUserDetails
成功,链已完成,我需要两个调用的一些额外处理结果。如果authLogin
失败或getUserDetails
失败,则应该进行错误处理(例如从throwable中获取http错误码或消息)。
由于我的方法有效,我知道这不是好的方法,如何优化它?我可以使用 flatMap
运算符代替嵌套的 observables 吗?
编辑:方法声明:
public static Map<String, String> prepareHeaders(String tokenType, String accessToken);
Observable<UserDetails> getUserDetails(@Path(value = "cityId", encoded = true) String cityId, @HeaderMap Map<String, String> headers);
最后一次尝试:
mcityService.authLogin(request, Utils.prepareHeaders())
.concatMap(response ->
{
final Map<String, String> headers = Utils.prepareHeaders(response.tokenType,response.accessToken);
return mcityService.getUserDetails(selectedCity.id, headers)
.map(userDetails -> new Object()
{
public AuthResponse ar = response;
public UserDetails ud = userDetails;
});
})
.doOnNext(responseDetails ->
{
AuthResponse ar = responseDetails.ar;
UserDetails ud = responseDetails.ud;
})
.doOnError(throwable ->
{
final String message = throwable.getMessage();
});
结果:.doOnNext
从未调用过,mcityService.getUserDetails
似乎从未调用过,.doOnError
也从未调用过(所以没有错误)。首先 mcityService.authLogin
调用 returns Observable<AuthResponse>
我真的不需要 subscribe
吗?
是的,你可以而且应该使用 flatMap
/ concatMap
/ switchMap
.
另外,抱歉,如果编码不好,我主要使用 RxJS,它有 pipable 运算符(更好!)。
mcityService.authLogin(request, Utils.prepareHeaders())
.concatMap(response -> {
final Map<String, String> headers = Utils.prepareHeaders(resp.tokenType,resp.accessToken);
return mcityService.getUserDetails(selectedCity.id, headers)
.map(userDetails -> ResponseUserDetails.of(response, userDetails));
})
.doOnNext(responseDetails -> {
// Hanlde ResponseUserDetails object
})
.doOnError(throwable -> {
// Handle exception
final String message = throwable.getMessage();
...
})
.subscribe(
responseDetails -> { ... },
throwable -> { ... }
);
如果您不想使用额外的 class,您可以即时创建一个 Object
return mcityService.getUserDetails(selectedCity.id, headers)
.map(userDetails -> new Object() {
public Response r = response;
public UserDetails ud = userDetails;
});
并通过
访问其字段
.doOnNext(responseDetails -> {
final Response r = responseDetails.r;
final UserDetails ud = responseDetails.ud;
...
})
static class ResponseUserDetails {
final Response response;
final UserDetails userDetails;
ResponseUserDetails(
final Response response,
final UserDetails userDetails) {
this.response = response;
this.userDetails = userDetails;
}
static ResponseUserDetails of(
final Response response,
final UserDetails userDetails) {
return new ResponseUserDetails(response, userDetails);
}
}
请看这段代码:
Disposable disposable = mcityService.authLogin(request,Utils.prepareHeaders())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(resp ->
{
mCompositeDisposable.add(mcityService.getUserDetails(selectedCity.id,Utils.prepareHeaders(resp.tokenType,resp.accessToken))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(userDetails ->
{
/*process resp and user details*/
}));
}, throwable ->
{
process errors
});
mCompositeDisposable.add(disposable);
}
所以基本上我需要调用authLogin
,如果成功,调用getUserDetails
(需要authLogin
调用结果中的一些字段),如果getUserDetails
成功,链已完成,我需要两个调用的一些额外处理结果。如果authLogin
失败或getUserDetails
失败,则应该进行错误处理(例如从throwable中获取http错误码或消息)。
由于我的方法有效,我知道这不是好的方法,如何优化它?我可以使用 flatMap
运算符代替嵌套的 observables 吗?
编辑:方法声明:
public static Map<String, String> prepareHeaders(String tokenType, String accessToken);
Observable<UserDetails> getUserDetails(@Path(value = "cityId", encoded = true) String cityId, @HeaderMap Map<String, String> headers);
最后一次尝试:
mcityService.authLogin(request, Utils.prepareHeaders())
.concatMap(response ->
{
final Map<String, String> headers = Utils.prepareHeaders(response.tokenType,response.accessToken);
return mcityService.getUserDetails(selectedCity.id, headers)
.map(userDetails -> new Object()
{
public AuthResponse ar = response;
public UserDetails ud = userDetails;
});
})
.doOnNext(responseDetails ->
{
AuthResponse ar = responseDetails.ar;
UserDetails ud = responseDetails.ud;
})
.doOnError(throwable ->
{
final String message = throwable.getMessage();
});
结果:.doOnNext
从未调用过,mcityService.getUserDetails
似乎从未调用过,.doOnError
也从未调用过(所以没有错误)。首先 mcityService.authLogin
调用 returns Observable<AuthResponse>
我真的不需要 subscribe
吗?
是的,你可以而且应该使用 flatMap
/ concatMap
/ switchMap
.
另外,抱歉,如果编码不好,我主要使用 RxJS,它有 pipable 运算符(更好!)。
mcityService.authLogin(request, Utils.prepareHeaders())
.concatMap(response -> {
final Map<String, String> headers = Utils.prepareHeaders(resp.tokenType,resp.accessToken);
return mcityService.getUserDetails(selectedCity.id, headers)
.map(userDetails -> ResponseUserDetails.of(response, userDetails));
})
.doOnNext(responseDetails -> {
// Hanlde ResponseUserDetails object
})
.doOnError(throwable -> {
// Handle exception
final String message = throwable.getMessage();
...
})
.subscribe(
responseDetails -> { ... },
throwable -> { ... }
);
如果您不想使用额外的 class,您可以即时创建一个 Object
return mcityService.getUserDetails(selectedCity.id, headers)
.map(userDetails -> new Object() {
public Response r = response;
public UserDetails ud = userDetails;
});
并通过
访问其字段.doOnNext(responseDetails -> {
final Response r = responseDetails.r;
final UserDetails ud = responseDetails.ud;
...
})
static class ResponseUserDetails {
final Response response;
final UserDetails userDetails;
ResponseUserDetails(
final Response response,
final UserDetails userDetails) {
this.response = response;
this.userDetails = userDetails;
}
static ResponseUserDetails of(
final Response response,
final UserDetails userDetails) {
return new ResponseUserDetails(response, userDetails);
}
}