简体   繁体   English

使用RxJava连锁两个改造的可观测量

[英]Chain two retrofit observables w/ RxJava

I want to execute 2 network calls one after another. 我想一个接一个地执行2个网络呼叫。 Both network calls return Observable. 两个网络调用都返回Observable。 Second call uses data from successful result of the first call, method in successful result of second call uses data from both successful result of the first and of the second call. 第二呼叫从所述第一呼叫的成功的结果使用数据,在第二个呼叫的成功结果的方法,从所述第二呼叫的所述第一的成功的结果,并使用数据。 Also i should be able to handle both onError "events" differently. 此外,我应该能够同时处理onError的“事件”是不同的。 How can i achieve this avoiding callback hell like in example below: 我怎样才能避免回调地狱,如下例所示:

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

I know about zip, but i want to avoid creating "Combiner class". 我知道zip,但我想避免创建“Combiner类”。

Update 1. Tried to implement akarnokd's answer: 更新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);
                }
            }));

However inside flatMap method compiler says it can't resolve methods of authResponse and users ( authResponse.getAccessToken() , users.get(0) etc). 但是在flatMap方法编译器中说它无法解析authResponse和users( authResponse.getAccessToken()users.get(0)等)的方法。 Im new to rx programming and lambdas - please tell me what's the problem. 我是rx编程和lambdas的新手 - 请告诉我这是什么问题。 Anyway code looks much cleaner now. 无论如何代码现在看起来更干净。

Update 2. 更新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);
            }));

Have done it like this, but now my network calls aren't executing at all. 这样做了,但现在我的网络电话根本没有执行。

Have you looked into flatMap()? 你看过flatMap()吗? If your aversion to it (or zip()) is the need to make an unnecessary class just to hold two objects, android.util.Pair might be an answer. 如果你厌恶它(或zip())是需要创建一个不必要的类只是为了保存两个对象,android.util.Pair可能是一个答案。 I'm not sure how to get exactly the error handling you're looking for, though. 不过,我不确定如何准确地获得您正在寻找的错误处理。

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

In addition to Anthony R.'s answer, there is a flatMap overload which takes a Func2 and pairs your primary and flattened values for you. 除了Anthony R.的答案之外,还有一个flatMap重载,它接受一个Func2并为你配对你的主要值和扁平值。 In addition, look at the onErrorXXX and onExceptionXXX operators for error manipulation, and chain them with your first and second Observables 另外,查看onErrorXXX和onExceptionXXX运算符以进行错误操作,并将它们与第一个和第二个Observables链接起来

first.onErrorReturn(1)
.flatMap(v -> service(v).onErrorReturn(2), (a, b) -> a + b);

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

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