Как ждать ответа на модификацию в rxjava - PullRequest
0 голосов
/ 03 мая 2018

Я использую retrofit2 с расширением rxjava.

У меня есть список URL REST API, и я хочу сделать это:

  • за каждого
    • проверить, существует ли соответствующий файл локально
    • если да: вызвать API и сохранить ответ или ошибку HTTP
    • если нет: сохранить персонализированную ошибку
  • вернуть список этих результатов

Моя проблема: apply возвращает (с пустым RequestResult) до получения ответа сервера. Я думаю, я понимаю, почему, но я не знаю, как это исправить, потому что мне нужно вернуть RequestResult, а не наблюдаемую модификацию.

Как это можно решить?

Вот мой код:

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

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Если вы выполняете вызов API в фоновом потоке, то вы можете вызвать его синхронно .... в вашем случае ваш модифицированный метод API изменится на следующий

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

, и вы позвоните по телефону restAPI.enroll(listItem.url).execute()

0 голосов
/ 03 мая 2018

Оператор flatMap() позволяет превратить одну наблюдаемую в другую наблюдаемую. У вас есть вложенная цепочка наблюдателей внутри вашей apply(), которая не является частью цепочки наблюдателей, поэтому она будет пустой, потому что она еще не завершена.

Чтобы исправить это, когда файл существует, верните наблюдаемое.

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

Если вам нужно зафиксировать в списке как ошибки, так и успехи, то вы можете добавить оператор map() для переноса RequestResult вокруг ответа и onErrorResumeNext() для переноса RequestResult вокруг ошибки перед оператором toList() .

...