Android okHttp重试政策

时间:2016-01-28 09:09:15

标签: java android okhttp okhttp3

我正在尝试创建一个简单的包装器,它将调用服务器下载信息并解析发送的二进制数据。 对于连接我正在使用名为okhttp的库,因为3G上的连接不是很可靠我决定使用以下函数实现一个非常简单的重试功能**(注意这个方法总是从后台线程调用)**

private InputStream callServer() throws ServerException, NoNetworkAvailableException, ConnectionErrorException {
        NetworkOperation networkOperation = getNetworkOperation();
        InputStream inputStream = null;
        //in case of network problems we will retry 3 times separated by 5 seconds before gave up
        while (connectionFailedRetryCounter < connectionFailedMaximumAllowedRetries()) {
            connectionFailedRetryCounter++;
            try {
                inputStream = networkOperation.execute();
                break;//if this line was reached it means a successfull operation, no need to retry .
            } catch (ConnectionErrorException e) {
                if (canRetryToConnect()) {
                    Utils.forceSleepThread(Constants.Communications.ConnectionFailedTrialCounter.SLEEP_BETWEEN_REQUESTS_MILLI);//retry after 5 secs (Thread.sleep)
                } else {
                    throw e;//I give up
                }
            }

        }
        return inputStream;

    }

    private boolean canRetryToConnect() {
        return (connectionFailedRetryCounter < connectionFailedMaximumAllowedRetries()) && !canceled;
    }

这是正确的方法吗?或者它已经由图书馆自己完成(没有必要实现这样的东西)?

这是方法execute()做的事情

public InputStream execute() throws ConnectionErrorException, NoNetworkAvailableException, ServerException {

    if (!Utils.isNetworkAvailable(context)) {
        throw new NoNetworkAvailableException();
    }

    Response response = doExecute();

    if (!response.isSuccessful()) {
        throw new ServerException(response.code());
    }

    return response.body().byteStream();
}

private Response doExecute() throws ConnectionErrorException {
    Response response;
    try {
        if (getRequestType() == RequestType.GET) {
            response = executeGet();
        } else {
            response = executePost();
        }
    } catch (IOException e) {
        throw new ConnectionErrorException();
    }
    return response;
}

1 个答案:

答案 0 :(得分:1)

如果抓住NoNetworkAvailableException,可以避免重试。如果您知道以下尝试将失败,请不要重试。

我会使connectionFailedMaximumAllowedRetries()成为常数。我怀疑你需要在任何时候改变变量。

实施exponential back off。你可以让它重试10次。每次,您将延迟乘以2(上限为几分钟)。例如:

  1. 尝试通话 - 失败
  2. 等一下
  3. 尝试通话 - 失败
  4. 等待2秒
  5. 尝试通话 - 失败
  6. 等待4秒
  7. ...
  8. 尝试通话 - 成功
  9. 这是非常典型的行为。如果发生短暂中断,将很快再次拨打电话并成功。如果停电时间较长,您不希望每隔几秒钟就一直打电话。这为您的代码提供了通话的最佳机会。显然,如果UI更改需要此调用,则应注意不要烦扰用户。