简体   繁体   English

Rxjava - 连锁可观察者

[英]Rxjava - chain observables

Please look at this code: 请看这段代码:

 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);
    }

So basically I need to call authLogin , if it succedes, call getUserDetails (some fields from authLogin call results are required), if getUserDetails succeded, chain is finished and I need some additional processing result from both calls. 所以基本上我需要调用authLogin ,如果成功,则调用getUserDetails (需要来自authLogin调用结果的某些字段),如果getUserDetails成功,则链完成,我需要两个调用的一些额外处理结果。 If authLogin fails or getUserDetails fails, error processing should be performed (for example, get http error code or message from throwable). 如果authLogin失败或getUserDetails失败,则应执行错误处理(例如,从throwable获取http错误代码或消息)。

As my approach works, I know it's not goot approach, how to optimize it? 由于我的方法有效,我知道这不是goot方法,如何优化它? Can I use flatMap operator instead nested observables? 我可以使用flatMap运算符代替嵌套的observable吗?

edit: Methods declarations: 编辑:方法声明:

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);

Final attempt: 最后的尝试:

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();

                });

Results: .doOnNext never called, mcityService.getUserDetails seems to be never called, .doOnError also never called (so there was no error). 结果: .doOnNext从未调用过, mcityService.getUserDetails似乎永远不会调用, .doOnError也从未调用过(因此没有错误)。 First mcityService.authLogin call returns Observable<AuthResponse> don't I really need subscribe ? 首先mcityService.authLogin调用返回Observable<AuthResponse>我真的不需要subscribe吗?

Yes, you can, and should use flatMap / concatMap / switchMap . 是的,你可以,并且应该使用flatMap / concatMap / switchMap
Also, sorry if it is not coded well, I primarily use RxJS, which has pipable operators (much better!). 对不起,如果编码不好,我主要使用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 -> { ... }
            );

If you don't want to use an additional class, you can create an Object on the fly 如果您不想使用其他类,则可以动态创建Object

return mcityService.getUserDetails(selectedCity.id, headers)
                   .map(userDetails -> new Object() { 
                           public Response r = response;
                           public UserDetails ud = userDetails;
                   });

And access its fields via 并通过访问其字段

.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);
   }
}

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM