error-handling - 改造错误响应处理

标签 error-handling

我正在使用翻新版2.3.0在我的应用程序中使用API​​,但是一周前我开始收到错误消息,并且现有代码无法在UI中显示错误消息。

以前,我使用errorBody.toString(),然后几个月后突然出现错误,然后上周我尝试使用errorBody.string(),但是它不起作用。现在,它正在工作。

我已经附上了服务器响应和错误处理的屏幕截图。这是我的代码以显示错误消息。

private static void showToastForError(retrofit2.Response<Object> response, int requestType) {
        if (response != null && response.errorBody() != null) {
            try {
                JSONObject jObjError = null;
                try {
                    jObjError = new JSONObject(response.errorBody() != null ? response.errorBody().toString() : "");
                    Toast.makeText(Application.getAppContext(), jObjError.getString("message"), Toast.LENGTH_LONG).show();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

最佳答案

我认为您应该自定义调用适配器来处理错误。
这是我的自定义适配器

public final class ErrorHandlingAdapter {
    /**
     * A callback which offers granular callbacks for various conditions.
     */
    public interface MyCallback<T> {
        /**
         * Called for [200, 300) responses.
         */
        void success(Response<T> response);

        /**
         * Called for 401 responses.
         */
        void unauthenticated(Response<?> response);

        /**
         * Called for [400, 500) responses, except 401.
         */
        void clientError(Response<?> response);

        /**
         * Called for [500, 600) response.
         */
        void serverError(Response<?> response);

        /**
         * Called for network errors while making the call.
         */
        void networkError(IOException e);

        /**
         * Called for unexpected errors while making the call.
         */
        void unexpectedError(Throwable t);
    }

    public interface MyCall<T> {
        void cancel();

        void enqueue(MyCallback<T> callback);

        MyCall<T> clone();

        boolean isExcute();
    }

    public static class ErrorHandlingCallAdapterFactory extends CallAdapter.Factory {
        @Override
        public CallAdapter<?> get(Type returnType, Annotation[] annotations,
                                  Retrofit retrofit) {
            if (getRawType(returnType) != MyCall.class) {
                return null;
            }
            if (!(returnType instanceof ParameterizedType)) {
                throw new IllegalStateException(
                        "MyCall must have generic type (e.g., MyCall<ResponseBody>)");
            }
            Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);
            Executor callbackExecutor = retrofit.callbackExecutor();
            return new ErrorHandlingCallAdapter<>(responseType, callbackExecutor);
        }

        private static final class ErrorHandlingCallAdapter<R> implements CallAdapter<R> {
            private final Type responseType;
            private final Executor callbackExecutor;

            ErrorHandlingCallAdapter(Type responseType, Executor callbackExecutor) {
                this.responseType = responseType;
                this.callbackExecutor = callbackExecutor;
            }

            @Override
            public Type responseType() {
                return responseType;
            }

            @Override
            public <R1> R adapt(Call<R1> call) {
                return (R) new MyCallAdapter(call, callbackExecutor);
            }

        }
    }

    /**
     * Adapts a {@link Call} to {@link MyCall}.
     */
    static class MyCallAdapter<T> implements MyCall<T> {
        private final Call<T> call;
        private final Executor callbackExecutor;

        MyCallAdapter(Call<T> call, Executor callbackExecutor) {
            this.call = call;
            this.callbackExecutor = callbackExecutor;
        }

        @Override
        public void cancel() {
            call.cancel();
        }

        @Override
        public void enqueue(final MyCallback<T> callback) {
            call.enqueue(new Callback<T>() {
                @Override
                public void onResponse(Call<T> call, Response<T> response) {

                    // on that executor by submitting a Runnable. This is left as an exercise for the reader.
                    callbackExecutor.execute(new Runnable() {
                        @Override
                        public void run() {
                            int code = response.code();
                            if (code >= 200 && code < 300) {
                                callback.success(response);
                            } else if (code == 401) {
                                if (Storage.getInstance().isLogin())
                                Storage.getInstance().logout(App.self().getApplicationContext());
                            } else if (code >= 400 && code < 500) {
                                callback.clientError(response);
                            } else if (code >= 500 && code < 600) {
                                callback.serverError(response);
                            } else {
                                callback.unexpectedError(new RuntimeException("Unexpected response " + response));
                            }
                        }
                    });

                }

                @Override
                public void onFailure(Call<T> call, Throwable t) {

                    // on that executor by submitting a Runnable. This is left as an exercise for the reader.
                    callbackExecutor.execute(new Runnable() {
                        @Override
                        public void run() {
                            if (t instanceof IOException) {
                                if (call.isCanceled()) {
                                    return;
                                }
                                callback.networkError((IOException) t);
                                Toast.makeText(App.self(), R.string.error_no_connect_internet, Toast.LENGTH_SHORT).show();
                            } else {
                                callback.unexpectedError(t);
                            }
                        }
                    });

                }
            });
        }

        @Override
        public MyCall<T> clone() {
            return new MyCallAdapter<>(call.clone(), callbackExecutor);
        }

        @Override
        public boolean isExcute() {
            return call.isExecuted();
        }
    }
}

在这里我的配置添加自定义 call 适配器
Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addCallAdapterFactory(new ErrorHandlingAdapter.ErrorHandlingCallAdapterFactory()) // custom call adapter
                .addConverterFactory(GsonConverterFactory.create())
                .client(getHeader())
                .build();

并处理请求,例如:
@GET("api/getSomething")
ErrorHandlingAdapter.MyCall<BaseResponse> getSomething(@Query("param"),...)

处理响应:
ErrorHandlingAdapter.MyCall<BaseResponse> mCalls = ApiUtils.getSomething(...);
    mCalls.enqueue(new ErrorHandlingAdapter.MyCallback<BaseResponse>() {
        @Override
        public void success(Response<BaseResponse> response) {
            //handle response
        }

        @Override
        public void unauthenticated(Response<?> response) {
            //handle unauthenticated error
        }

        @Override
        public void clientError(Response<?> response) {
            //handle clientError error
        }

        @Override
        public void serverError(Response<?> response) {
           //handle serverError error
        }

        @Override
        public void networkError(IOException e) {
           //handle networkError error
        }

        @Override
        public void unexpectedError(Throwable t) {
            //handle unexpectedError error
        }
    }

关于error-handling - 改造错误响应处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50056827/

相关文章:

error-handling - 使用php,Mysqli将一组复选框发送到数据库时遇到问题

c - 处理用户输入中的 EOF

jquery - Rails 和 ajax 全局错误处理问题

php - PHP网站的错误处理

c# - ViewResult 不使用 ASP.NET MVC 在 ASP.NET WebForms 项目中呈现页面内容

r - prettyNum(.Internal(format(x,trim,digits,nsmall,width,3L,: invalid 'nsmall' argument

php - 回收自定义错误日志

c# - C#/ASP-引发异常

swift - Swift 中的错误处理 : Error from one enum to another

php - Apache2错误200 OK