【问题标题】:Retrofit 2 synchronous call error handling for 4xx ErrorsRetrofit 2 4xx 错误的同步调用错误处理
【发布时间】:2017-01-14 02:24:34
【问题描述】:

我正在使用 android-priority-jobqueue 并且我使用改造来对我的 rest api 进行同步调用,但我不确定如何处理诸如 401 Unauthorized 错误之类的错误,我发回 json 来说明错误。进行异步调用时很简单,但我正在为作业经理调整我的应用程序。下面是 IO 异常的简单尝试捕获,但是 401 的 422 等?如何做到这一点?

try {
    PostService postService = ServiceGenerator.createService(PostService.class);
    final Call<Post> call = postService.addPost(post);
    Post newPost = call.execute().body();

    // omitted code here

} catch (IOException e) {
    // handle error
}

编辑

改造响应对象的使用对我来说是关键,返回改造响应对象让我能够

Response<Post> response = call.execute();

if (response.isSuccessful()) {
    // request successful (status code 200, 201)
    Post result = response.body();

    // publish the post added event
    EventBus.getDefault().post(new PostAddedEvent(result));
} else {
    // request not successful (like 400,401,403 etc and 5xx)
    renderApiError(response);
}

【问题讨论】:

    标签: android error-handling retrofit2 synchronous


    【解决方案1】:

    检查响应代码并显示相应的消息。

    试试这个:

     PostService postService = ServiceGenerator.createService(PostService.class);
     final Call<Post> call = postService.addPost(post);
    
    Response<Post> newPostResponse = call.execute();
    
    // Here call newPostResponse.code() to get response code
    int statusCode = newPostResponse.code();
    if(statusCode == 200)
        Post newPost = newPostResponse.body();
    else if(statusCode == 401)
        // Do some thing... 
    

    【讨论】:

    • 谢谢,使用响应对象正是我所需要的,干杯:)
    • 很高兴为您提供帮助。
    • 做同样的事情我得到一个java.lang.NumberFormatException: Invalid double: "" 错误,因为 call.execute 返回一个空值的 json。我想获取 call.execute() 的主体并在执行其他任何操作之前对其进行检查。当我写类似“Response newPostResponse = call.execute();”我确实收到错误,因为正文不是正确的
    • @MaximeClaude 检查我的答案here 以获取字符串中的响应
    • 这是基本的。没有处理可能的 http 错误的调用是绝对没用的。我想知道为什么在retrofit2-tutorials 中甚至讨论了没有这种错误处理的方法!谢谢你:)
    【解决方案2】:

    对每个响应都进行 401 检查并不是一个很好的方法。相反,可以在基础级别应用此检查,即在为 Retrofit 创建对象时,通过拦截器。看看:

    public synchronized static Retrofit getClientWithRetry(final Context ctx) {
        if (clientWithRetry == null) {
            Interceptor responseCodeInterceptor = new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    Response response = chain.proceed(request);
                    if (response.code() == 401) {
                        Log.d(LOG_TAG, "Intercepted Req: " + response.toString());
                        Response r = retryWithFreshToken(request, chain);
                        return r;
                    }
                    return response;
                }
            };
    
            int cacheSize = 10 * 1024 * 1024; // 10 MB
            Cache cache = new Cache(ctx.getCacheDir(), cacheSize);
    
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            OkHttpClient client = new OkHttpClient.Builder()
                    .addInterceptor(logging)
                    .addInterceptor(responseCodeInterceptor)
                    .cache(cache)
                    .build();
    
            Retrofit.Builder builder = new Retrofit.Builder()
                    .baseUrl(API_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(client);
            clientWithRetry = builder.build();
        }
        return clientWithRetry;
    }
    

    如果在内部观察到 401,则可以发出新的链式请求并且可以获取令牌。可以完成原始请求的帖子。取自Retrofit retry tutorial

    【讨论】:

    • 如何处理超时异常?我不喜欢为每个请求都处理它。
    猜你喜欢
    • 2015-07-30
    • 2017-01-01
    • 2020-03-13
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    • 2017-05-13
    • 2023-03-20
    • 1970-01-01
    相关资源
    最近更新 更多