java - 使用 RxJava 链两个改造 observables

标签 java android retrofit reactive-programming rx-java

我想一个接一个地执行 2 个网络调用。两个网络调用都返回 Observable。第二次调用使用第一次调用的成功结果中的数据,第二次调用成功结果中的方法使用第一次和第二次调用的both成功结果中的数据。我也应该能够以不同的方式处理 both onError “事件”。我怎样才能避免回调 hell ,如下例所示:

       API().auth(email, password)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<AuthResponse>() {
                @Override
                public void call(final AuthResponse authResponse) {
                    API().getUser(authResponse.getAccessToken())
                            .subscribe(new Action1<List<User>>() {
                                @Override
                                public void call(List<User> users) {
                                    doSomething(authResponse, users);
                                }
                            }, new Action1<Throwable>() {
                                @Override
                                public void call(Throwable throwable) {
                                    onErrorGetUser();
                                }
                            });
                }
            }, new Action1<Throwable>() {
                @Override
                public void call(Throwable throwable) {
                    onErrorAuth();
                }
            });

我知道 zip,但我想避免创建“Combiner 类”。

更新 1。 试图实现 akarnokd 的回答:

         API()
            .auth(email, password)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .flatMap(authResponse -> API()
                    .getUser(authResponse.getAccessToken())
                    .doOnError(throwable -> {
                        getView().setError(processFail(throwable));
                    }), ((authResponse, users) -> {
                // Ensure returned user is the which was authenticated
                if (authResponse.getUserId().equals(users.get(0).getId())) {
                    SessionManager.getInstance().initSession(email, password, authResponse.getAccessToken(), users.get(0));
                    getView().toNews();
                } else {
                    getView().setError(R.string.something_went_wrong);
                }
            }));

但是 flatMap 方法编译器内部说它无法解析 authResponse 和用户的方法 (authResponse.getAccessToken(), users.get(0)等)。我是 rx 编程和 lambdas 的新手——请告诉我有什么问题。无论如何,代码现在看起来干净多了。

更新 2。

API()
            .auth(email, password)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnError(throwable -> getView().setError(processFail(throwable)))
            .flatMap((AuthResponse authResponse) -> API()
                    .getUser(authResponse.getAccessToken())
                    .doOnError(throwable -> getView().setError(processFail(throwable))), ((AuthResponse authResponse, List<User> users) -> {
                            // Ensure returned user is the which was authenticated
                            if (authResponse.getUserId().equals(users.get(0).getId())) {
                                SessionManager.getInstance().initSession(email, password, authResponse.getAccessToken(), users.get(0));
                                getView().toNews();
                            }
                            return Observable.just(this);
            }));

已经这样做了,但现在我的网络调用根本没有执行。

最佳答案

你研究过 flatMap() 吗?如果您对它(或 zip())的反感是需要创建一个不必要的类来保存两个对象,那么 android.util.Pair 可能是一个答案。不过,我不确定如何获得您正在寻找的错误处理。

       API().auth(email, password)
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .flatMap(new Func1<AuthResponse, Observable<List<User>>>() {
          @Override
          public Observable<List<User>> call(AuthResponse authResponse) {
            return API().getUser(authResponse.getAccessToken());
          }
        }, new Func2<AuthResponse, List<User>, Pair<AuthResponse, List<User>>>() {
          @Override
          public Pair<AuthResponse, List<User>> call(AuthResponse authResponse, List<User> users) {
            return new Pair<>(authResponse, users);
          }
        }).subscribe(new Action1<Pair<AuthResponse, List<User>>>() {
          @Override
          public void call(Pair<AuthResponse, List<User>> pair) {
            doSomething(pair.first, pair.second);
          }
        }, new Action1<Throwable>() {
          @Override
          public void call(Throwable throwable) {
            // not sure how to tell which one threw the error
          }
        });

关于java - 使用 RxJava 链两个改造 observables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30269011/

相关文章:

java - 字符串操作,从同一行提取某些值

android - 如何在Android中获取Listview项选择的计数

android - GoogleCloudMessaging.unregister 是否删除 token

java - 如何为一个按钮添加多个操作

java - 将字符串解析为 JSON

java - 无法捕获全局热键(不是基于窗口的应用程序)

java - 实现接口(interface)和扫描仪属性

java - 为什么 Retrofit 不能用方括号正确编码查询字符串?

Android:使用 Moshi 适配器解析内部非结构化 Json

java - 使用 Retrofit 的并行 HTTP 请求