Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/179.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 改装2和RxJava错误处理操作符_Android_Retrofit_Rx Java - Fatal编程技术网

Android 改装2和RxJava错误处理操作符

Android 改装2和RxJava错误处理操作符,android,retrofit,rx-java,Android,Retrofit,Rx Java,我在我的项目中使用的是改造2,带有可观察的界面和结果包装器。例如: @POST("api/login") Observable<Result<LoginResponse>> login(@Body LoginRequest request); @POST(“api/登录”) 可观察的登录(@Body LoginRequest请求); 我需要结果包装器从响应中获得更多的信息,而不仅仅是序列化对象(例如头、http状态…) 问题是,对于结果包装器,网络调用不会引发任何异常

我在我的项目中使用的是改造2,带有可观察的界面和结果包装器。例如:

@POST("api/login")
Observable<Result<LoginResponse>> login(@Body LoginRequest request);
@POST(“api/登录”)
可观察的登录(@Body LoginRequest请求);
我需要结果包装器从响应中获得更多的信息,而不仅仅是序列化对象(例如头、http状态…)

问题是,对于结果包装器,网络调用不会引发任何异常。可以通过调用result.error()在结果中找到异常

如果我想利用RxJava错误运算符,我应该怎么做?
例如,我想在网络错误上使用retry操作符,但retry操作符仅在可观察对象引发异常时才起作用。

您应该检查引发的Throwable是否是HttpException的实例。

这是我提出的解决方案。 如果我会改进它,我会在这里发布更改

我的问题的解决方案(异常被改型吞没,而不是由RxJava处理)是Observable.error方法,该方法创建一个只发出错误的新Observable,因此我可以“重新引发”异常

我创建了一个可观察的转换器,以附加到每个发出改装结果的rest调用。 此转换器获取一个可观察>,如果响应没有错误,则将其转换为可观察>。如果有错误,它将返回一个带有自定义Http*异常的Observable.error,稍后我可以在OneError回调中的Observer中处理该异常。 我将其作为名为ObservateTransformations.resultToResponseWithHttpErrorHandling的实用程序类的静态方法

这是:

public class ObservableTransformations {

public static <T> Observable.Transformer<Result<T>, Response<T>> resultToResponseWithHttpErrorHandling() {
    return observable -> observable.flatMap(r -> {
        Observable<Response<T>> returnObservable = Observable.just(r.response());
        if (r.isError()) {
            Throwable throwable = r.error();
            if (throwable instanceof IOException) {
                Timber.e(throwable, "Retrofit connection error.");
                // TODO Check this cases
                if (throwable instanceof java.net.ConnectException) {
                    returnObservable = Observable.error(new HttpNoInternetConnectionException());
                } else if (throwable instanceof SocketTimeoutException) {
                    returnObservable = Observable.error(new HttpServerDownException());
                } else {
                    returnObservable = Observable.error(new HttpNoInternetConnectionException());
                }
            } else {
                Timber.e(throwable, "Retrofit general error - fatal.");
                returnObservable = Observable.error(new HttpGeneralErrorException(r.error()));
            }
        } else {
            Response<T> retrofitResponse = r.response();
            if (!retrofitResponse.isSuccess()) {
                int code = retrofitResponse.code();
                String message = "";
                try {
                    message = retrofitResponse.errorBody().string();
                } catch (IOException e) {
                    Timber.e(e, "Error reading errorBody from response");
                }
                Timber.i("Server responded with error. Code: " + code + " message: " + message);
                Throwable t = null;
                if (NetworkUtils.isClientError(code)) {
                    t = new HttpClientException(retrofitResponse.code(), message);
                } else if (NetworkUtils.isServerError(code)) {
                    t = new HttpServerErrorException(retrofitResponse.code(), message);
                }
                returnObservable = Observable.error(t);
            }
        }
        return returnObservable;
    }).retryWhen(new RetryWithDelayIf(3, 1000, t -> {
        return (t instanceof HttpNoInternetConnectionException) || (t instanceof HttpServerDownException);
    }));
}

}

在观测者的onError中,您终于可以处理Http*异常了。

很抱歉,我认为您不理解这个问题。顺便说一句,如果Reformation 2无法到达服务器(没有internet连接,服务器关闭..),它现在会抛出一个通用IOException。请查看Reformation.Builder中描述如何重写RxJavaCallAdapterFactory的链接,在那里您可以在Observable.onResumeErrorNext/Observable.onDoNext()中捕获对象看起来是一个可能对我的问题有帮助的解决方案。请看我的问题,也许我们可以为社区的利益想出一个很好的通用解决方案。
public class RetryWithDelayIf implements
    Func1<Observable<? extends Throwable>, Observable<?>> {

private final int maxRetries;
private final int retryDelayMillis;
private int retryCount;
private Func1<Throwable, Boolean> retryIf;

public RetryWithDelayIf(final int maxRetries, final int retryDelayMillis, Func1<Throwable, Boolean> retryIf) {
    this.maxRetries = maxRetries;
    this.retryDelayMillis = retryDelayMillis;
    this.retryCount = 0;
    this.retryIf = retryIf;
}

@Override
public Observable<?> call(Observable<? extends Throwable> attempts) {
    return attempts.zipWith(Observable.range(1, maxRetries + 1), (n, i) -> {
        return new Tuple<Throwable, Integer>(n, i);
    })
            .flatMap(
                    ni -> {
                        if (retryIf.call(ni.getFirst()) && ni.getSecond() <= maxRetries) {
                            return Observable.timer((long) Math.pow(2, ni.getSecond()), TimeUnit.SECONDS);
                        } else {
                            return Observable.error(ni.getFirst());
                        }
                    });
}

}
restService.login(new LoginRestRequest(username, password))
                .compose(ObservableTransformations.resultToResponseWithHttpErrorHandling());