简体   繁体   English

如何在rxjava中等待改造响应

[英]How to wait for retrofit response in rxjava

I use retrofit2 with rxjava extension. 我使用带有rxjava扩展名的retrofit2。

I have a list of REST API urls and want to do this: 我有一个REST API网址列表,并希望这样做:

  • for each 每个
    • check whether a corresponding file locally exists 检查本地是否存在对应的文件
    • if yes: call the API and store the response or the HTTP error 如果是:调用API并存储响应或HTTP错误
    • if not: store a customized error 如果不是:存储自定义错误
  • return the list of those results 返回这些结果的列表

My problem is: apply returns (with an empty RequestResult ) before the server response is received. 我的问题是:在收到服务器响应之前apply返回(带有空的RequestResult )。 I think, I understand why, but I don't know how to fix it, because I need to return a RequestResult and not the Retrofit observable. 我想,我知道为什么,但是我不知道如何解决它,因为我需要返回一个RequestResult而不是Retrofit可观察到的。

How can this be solved? 如何解决呢?

Here is my code: 这是我的代码:

@GET
Observable<Response<ResponseBody>> enroll(@Url String url);


class RequestResult {
    CustomException error;
    Response<ResponseBody> response;
}

Observable<ClassOfListItem> observable = Observable.fromIterable(listOfItems);

observable
    .flatMap(new Function<ClassOfListItem, ObservableSource<RequestResult>>() {

        @Override
        public ObservableSource<RequestResult> apply(ClassOfListItem listItem) throws Exception {

            RequestResult requestResult = new RequestResult();
            if (fileExists(listItem.url))   {
                Observable<Response<ResponseBody>> callObservable = restAPI.enroll(listItem.url)
                    .subscribeOn(Schedulers.io());

                callObservable
                    .subscribe(new DisposableObserver<Response<ResponseBody>>() {
                        @Override
                        public void onNext(Response<ResponseBody> responseBodyResponse) {
                            onPremiseEnrollmentResult.response = responseBodyResponse;
                        }
                        @Override
                        public void onError(Throwable e) {
                            onPremiseEnrollmentResult.error = new CustomException(e);
                        }
                        @Override
                        public void onComplete() {
                        }
                    });
            }
            else {
                requestResult.error = new CustomException("file not found");
            }
            return Observable.just(requestResult);
        }
    }
    .toList()
    .observerOn(AndroidScheduler.mainThread())
    .subscribe(new DisposableSingleObserver<List<RequestResult>>() {
        @Override
        public void onError(Throwable e) {
            Log.d("onError", e.getMessage());
        }
        @Override
        public void onSuccess(List<RequestResult> requestResults) {
            // parse results
        }
    }
 )

The flatMap() operator allows you to turn one observable into a different observable. flatMap()运算符使您可以将一个可观察对象转换为另一个可观察对象。 You have a nested observer chain inside your apply() which is not part of the observer chain, so it will be empty because it has not completed yet. 您的apply()有一个嵌套的观察者链,它不是观察者链的一部分,因此将是空的,因为尚未完成。

To fix this, when the file exists, return the observable. 为了解决这个问题,当文件存在时,返回observable。

observable
  .flatMap(new Function<ClassOfListItem, ObservableSource<RequestResult>>() {
    @Override
    public ObservableSource<RequestResult> apply(ClassOfListItem listItem) throws Exception {
        RequestResult requestResult = new RequestResult();
        if (fileExists(listItem.url))   {
            return restAPI.enroll(listItem.url)
                .subscribeOn(Schedulers.io());
        }
        return Observable.error( new CustomException("file not found") );
    }
}
.toList()
.observerOn(AndroidScheduler.mainThread())
.subscribe(new DisposableSingleObserver<List<RequestResult>>() {
    @Override
    public void onError(Throwable e) {

        Log.d("onError", e.getMessage());
    }

    @Override
    public void onSuccess(List<RequestResult> requestResults) {
        // parse results
    }
}

If you need to capture both errors and successes into the list, then you can add map() operator to wrap RequestResult around the response and onErrorResumeNext() to wrap RequestResult around the error before the toList() operator. 如果您需要将错误和成功都捕获到列表中,则可以在toList()运算符之前添加map()运算符以将RequestResult包裹在响应周围,将onErrorResumeNext()包裹在RequestResult周围的错误周围。

If you are making api call on background thread then what you can do is invoke it synchronously....in your case your retrofit api method would change to following 如果您要在后台线程上进行api调用,那么您可以做的是同步调用它。...在您的情况下,您的api改装方法将变为以下内容

Call<Response<ResponseBody>> enroll(@Url String url);

and you'd invoke by calling restAPI.enroll(listItem.url).execute() 并且可以通过调用restAPI.enroll(listItem.url).execute()进行调用

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

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