2016-01-28 3 views
3

Я пытаюсь создать простую оболочку, которая вызовет сервер для загрузки информации и разбора отправленных двоичных данных. для подключения Я использую библиотеку, называемую okhttp, поскольку соединение с 3G не очень надежное. Я решил реализовать очень простую функцию повторной попытки, используя следующую функцию ** (Обратите внимание, что этот метод будет всегда вызываться из фона резьба) **Android okHttp Retry policy

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; 
    } 

это правильный способ сделать это? или это уже сделана библиотекой, она сама (нет необходимости реализовывать что-либо подобное)?

Вот что метод выполнения() делать

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

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

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

Внештатный exponential back off. Вы можете повторить попытку 10 раз. Каждый раз вы умножаете задержку на 2 (с крышкой в ​​несколько минут). Например:

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

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

+0

Я только повторю попытку в случае ConnectionErrorException, если возникло какое-либо другое исключение (например: NoNetworkAvailableException), цикл прерывается, и исключение будет распространено на следующий уровень (все же я считаю, что мой код сложный и не читаемый как есть, я буду работать над упрощением потока). экспоненциальная задняя идея велика –