Политика повторных попыток Android okHttp

Я пытаюсь создать простую оболочку, которая вызовет сервер, загрузит информацию и проанализирует отправленные двоичные данные. для соединения я использую библиотеку с именем 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;
}

person A.Alqadomi    schedule 28.01.2016    source источник


Ответы (1)


Вы можете избежать повторной попытки, если поймаете NoNetworkAvailableException. Не повторяйте попытку, если вы знаете, что следующие попытки все равно потерпят неудачу.

Я бы сделал connectionFailedMaximumAllowedRetries() константой. Я сомневаюсь, что вам нужно будет изменить переменную в любой момент.

Реализуйте экспоненциальный откат. Вы можете повторить попытку 10 раз. Каждый раз вы умножаете задержку на 2 (с ограничением в несколько минут). Например:

  1. Попробуйте позвонить - не удалось
  2. Подождите 1 секунду
  3. Попробуйте позвонить - не удалось
  4. Подождите 2 секунды
  5. Попробуйте позвонить - не удалось
  6. Подождите 4 секунды
  7. ...
  8. Попробуйте позвонить - получилось

Это очень типичное поведение. В случае кратковременного отключения вызов будет сделан снова очень быстро и успешно. В случае более длительного отключения вы не хотите звонить постоянно каждые несколько секунд. Это дает вашему коду наилучшие шансы на выполнение вызова. Очевидно, следует обратить внимание на то, чтобы не раздражать пользователя, если этот вызов требуется для изменения пользовательского интерфейса.

person Knossos    schedule 28.01.2016
comment
Я только повторяю попытку в случае ConnectionErrorException, если возникнет какое-либо другое исключение (например, NoNetworkAvailableException), цикл прервется, и исключение будет распространено на следующий уровень (тем не менее я думаю, что мой код сложен и не читается как есть, я буду работать над упрощением потока). идея экспоненциального отката отличная - person A.Alqadomi; 28.01.2016