RxJava + Retrofit +民意调查

时间:2016-05-11 10:40:49

标签: java android rx-java retrofit2 rx-android

我有一个Retrofit电话,想要每隔30秒召回一次。为此,我使用Observable.interval(0, 30, TimeUnit.SECONDS)

Observable
    .interval(0, 30, TimeUnit.SECONDS)
    .flatMap(x -> RestApi.instance().getUsers())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(list -> {
                    // ...
               },
               error -> Timber.e(error, "can't load users"));

我的问题:如果api调用失败,则调用onError并且订阅取消订阅并且轮询不再有效: - (

为了捕捉api错误,我添加了retryWhen

Observable
    .interval(0, 30, TimeUnit.SECONDS)
    .flatMap(x -> RestApi.instance().getUsers()
                         .retryWhen(errors -> errors
                             .flatMap(error -> Observable.timer(15, TimeUnit.SECONDS))))
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(list -> {
                   // ...
               },
               error -> Timber.e(error, "can't load users"));

这会捕获错误,但我会在一段时间内收到多个api调用。每30秒我得到一个新的轮询信号,它以新的api请求结束。但是如果api请求失败,它会自行重试。所以我有一个新请求加上所有重试。

我的问题:如何在不取消订阅民意调查信号的情况下处理api错误?

4 个答案:

答案 0 :(得分:10)

了解如何正确使用retryWhenrepeatWhenhttp://blog.danlew.net/2016/01/25/rxjavas-repeatwhen-and-retrywhen-explained/

以及如何使用onError运算符: http://blog.danlew.net/2015/12/08/error-handling-in-rxjava/

这很简单Rx :)我不会给你一个最终解决方案,只是玩弄它并尝试理解这里的流程。

答案 1 :(得分:1)

如果您希望getUsers请求在请求失败时未在onError结束,而不是返回Observable<yourUserType> getUsers(),请返回Observable<Response<yourUserType>> getUsers()。这样您就可以拦截Response对象中的网络错误。

此方法仅在您使用改装2.x

时有效

答案 2 :(得分:0)

您可以使用onErrorResumeNext或onExceptionResumeNext并在那里传递&#34;错误&#34;值。 您可以查找其他错误处理,具体取决于您的需求here

答案 3 :(得分:0)

您可以使用此代码,在此代码中实现数字尝试和请求之间的时间延迟

private static int COUNTER_START = 1;
private static final int ATTEMPTS = 6;
private static final int ORIGINAL_DELAY_IN_SECONDS = 2;

remoteData.getAllRides(idSearch)
            .repeatWhen(new Func1<Observable<? extends Void>, Observable<?>>() {
                        @Override
                        public Observable<?> call(Observable<? extends Void> observable) {
                            return observable.flatMap(new Func1<Void, Observable<?>>() {
                                @Override
                                public Observable<?> call(Void aVoid) {
                                    if(COUNTER_START > ATTEMPTS){
                                        throw new RuntimeException();
                                    }
                                    COUNTER_START++;
                                    return Observable.timer(ORIGINAL_DELAY_IN_SECONDS, TimeUnit.SECONDS);
                                }
                            });
                        }
                    })
            .takeUntil(new Func1<RideResponse, Boolean>() {
                @Override
                public Boolean call(RideResponse rideResponse) {
                    return rideResponse.getState().equals("finished");//this is the validation finish polling

                }
            }).filter(new Func1<RideResponse, Boolean>() {
                @Override
                public Boolean call(RideResponse rideResponse) {
                    return rideResponse.getState().equals("finished"); //this is the validation finish polling
                }
            }).map(rideResponse -> Log.e("",rideResponse.toString()))
        .doOnError(err -> Log.e("Polling", "Error retrieving messages: " + err));