【问题标题】:Good approach to manually retry requests in Retrofit Android在 Retrofit Android 中手动重试请求的好方法
【发布时间】:2014-06-18 13:20:31
【问题描述】:

我了解改造会自动重试失败,但我想检查特定错误。如果错误是由于某个 HTTP 代码引起的,我需要在修改后重试该请求。

这可以使用同步调用轻松完成,但我正在进行异步调用(通过 传递回调)。当我在回调中收到错误时,我想重试请求 - 但我所拥有的只是 RetrofitError 对象(我丢失了请求正文)。

我有来自同一个活动的多个请求(同时),因此我避免保存所有请求并在成功时将它们无效。

有没有更好的方法来实现这个要求?

【问题讨论】:

  • 你在这方面有什么收获吗?目前必须大规模实现这一点,而我的手动重试方法似乎有点臃肿。
  • @JoshPinter OkHttp 刚刚添加了一个Interceptor,非常适合这个。请参阅下面的my answer
  • @mattblang 干杯,我去看看!

标签: android retrofit


【解决方案1】:

如果您使用OkHttp 作为您的HttpClient 并已更新为Retrofit >= 1.9.0,那么您可以使用新的Interceptor。具体来说,Application Interceptor 会让你retry and make multiple calls

您可以看到example pseudocode 我发布了关于处理过期令牌的类似问题。

另请注意,Retrofit 2.0 根据this GitHub ticket 将具有Interceptors。这将消除对OkHttp 的依赖,但我仍然建议使用它。

【讨论】:

    【解决方案2】:

    您可以尝试以下方法。首先是网络请求方式:

    void getDataFromServer(final int dataId) {
         ...
    
        dataService.getDataFromServer(dataId, new Callback<ResultData>() {
            @Override
            public void success(final ResultData data, final Response response) {
                retries.set(0);
                ...
            }
    
            @Override
            public void failure(RetrofitError error) {
                if (RetrofitErrorHandler.retry(activity, progressDialog, error, retries, activity.getString(R.string.error_getting_data))) {
                    getDataFromServer(dataId);// retry this method
                } else {
                   // let user know we counldn't get data
                   ...
                }
            }
        });
    
    }
    

    在这里您可以检查是否应该重试请求,如果我们应该重试则返回 true,如果不应该重试则返回 false。

    重试的前半部分检查错误的状态代码(参见r.getStatus())是否等于您感兴趣的状态代码(参见STATUS_CODE_RETRY),它可以是任何服务器状态代码(例如401、404) . 等等)。

    重试的后半部分首先检查它是否是网络错误(参见error.isNetworkError()),如果是,则增加重试计数器并返回true,这意味着将重试网络请求。如果错误网络错误(请参阅error.isNetworkError())并且重试计数器大于您希望的最大重试次数(请参阅NUM_RETRIES),则它返回false,因此请求不会再次被触发。下一部分是无连接检查,其中发生了网络错误但不是超时,因此它一定是连接问题。此检查返回 false,因为不应重试网络请求并且应通知用户连接问题。最后的检查是非网络错误检查,它表示发生的错误不是网络错误的结果。再次返回 false,因此不会重试请求并通知用户。

    public static boolean retry(Activity act, RetrofitError error, AtomicInteger retries, String uploadErrorMsg){
        // this is the first half of the retry check
        Response r = error.getResponse();
        if (r != null && r.getStatus() == STATUS_CODE_RETRY){
            Log.v(TAG, "STATUS_CODE_RETRY!");
            ...
            return true;
        }
        // this is the second half of the retry check
        if (error.isNetworkError()) {
            if (error.getCause() instanceof SocketTimeoutException) {//connection timeout check
                if(retries.incrementAndGet() < NUM_RETRIES){ // retry if you can
                    return true;
                } else { // if you can't retry anymore
                    retries.set(0);
                    Log.i(TAG, act.getClass().getSimpleName() + " has no more retries " + act.getString(R.string.timeout_msg));
                    return false;
                }
            } else {//no connection check
                retries.set(0);
                Log.i(TAG, act.getClass().getSimpleName() + " " + act.getString(R.string.timeout_msg)+ " " + uploadErrorMsg);
                return false;
            }
        } else { //non network error check
            retries.set(0); 
            Log.i(TAG, act.getClass().getSimpleName() + " " + act.getString(R.string.err_msg)+ " " + uploadErrorMsg);
            return false;
        }
    }  
    

    希望这会有所帮助。

    【讨论】:

    • 很好的答案,但你能不能用英文总结一下retry 到底在做什么?
    • retry 应命名为 shouldRetry 或类似名称 - 它会根据已重试的次数和当前 API 调用的错误类型检查是否应重试请求。跨度>
    • 好答案,有道理,但对getDataFromServer 方法中的retries 变量感到非常困惑,它来自哪里?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 2016-12-26
    • 1970-01-01
    • 2014-03-27
    相关资源
    最近更新 更多