首页 > 解决方案 > Rxjava - 链 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一些字段),如果成功,链完成,我需要两个调用的一些额外处理结果。如果失败或失败,则应该进行错误处理(例如,从 throwable 中获取 http 错误代码或消息)。authLogingetUserDetailsauthLogingetUserDetails

当我的方法有效时,我知道这不是很好的方法,如何优化它?我可以使用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通话返回吗?Observable<AuthResponse>subscribe

标签: javaobservablerx-java2flatmap

解决方案


是的,您可以而且应该使用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 -> { ... }
            );

如果您不想使用其他类,可以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);
   }
}

在此处输入图像描述


推荐阅读