2015-09-19 34 views
6

Sto utilizzando OkHttp con Retrofit per effettuare le richieste di rete della mia app. Sto anche utilizzando Interceptor per l'autenticazione e ritentare le richieste, se necessario.Errore di ritorno dall'intercettore OKHttp (utilizzando il retrofit)

Il server a volte presenta problemi temporanei e restituisce un corpo vuoto anche se lo stato della risposta è 200 OK. Ciò causa l'arresto anomalo della mia app, poiché viene chiamato il blocco di successo del callback di Retrofit, l'oggetto personalizzato restituito (e analizzato con GSON) è nullo e il codice nella callback di successo presuppone che venga restituito un oggetto.

Ho già segnalato questo al team del server, ma voglio correggerlo anch'io, senza dover avvolgere tutto il codice di callback di successo su tutta l'app con assegni nulli.

Currenty Sono propenso a due opzioni, anche se altre idee sono i benvenuti: 1) Non ritorno dalla intercettore (è presente anche possibile) e solo la visualizzazione di un errore di dialogo 2) Ritornando qualcosa che vi farà retrofit? chiamare la parte di errore del callback.

Il mio codice è di sotto. Come puoi vedere, riprovo la richiesta per un massimo di 3 volte quando viene ricevuto un corpo vuoto.

@Override 
public Response intercept(Chain chain) throws IOException 
{ 
    // First 
    Request request = chain.request(); 
    Response response = chain.proceed(request); 

    .... 
    .... 
    .... 

    // Retry empty body response requests for a maximum of 3 times 
    Integer retryMaxCount = 3; 
    MediaType contentType = response.body().contentType(); 
    String bodyString = response.body().string(); 

    while (bodyString.length() == 0 && retryMaxCount > 0) 
    { 
     //Empty body received!, Retrying... 

     retryMaxCount--; 
     response = chain.proceed(request); 
     bodyString = response.body().string(); 
    } 

    if (bodyString.length() != 0) 
    { 
     // Create and return new response because it was consumed 
     ResponseBody newResponseBody = ResponseBody.create(contentType, bodyString); 
     return response.newBuilder().body(newResponseBody).build(); 
    } 
    else 
    { 
     // WHAT TO WRITE HERE??? 
    } 
} 

Grazie mille.

+8

Perché non generare un'eccezione dall'intercettore? – mastov

+3

Grazie mille. E 'stato semplice Se lo pubblichi come risposta, lo accetto. :) –

+0

@mastov Se si genera un errore lì, l'app non si bloccherà? Come gestisci l'errore/propagalo alla richiamata? – Singed

risposta

0

Ho appena avuto lo stesso scenario e questo post mi ha aiutato a implementare la soluzione. Grazie a @mastov per indicare la giusta direzione.

Utilizzo di una API back-end che restituisce sempre HTTP 200 anche se si è verificato un errore. Questo è stato il mio esempio di risposta di un errore

{"status":403,"message":"Bad User credentials","time":1495597740061,"version":"1.0"} 

Ecco una semplice implementazione per completare questa risposta.

public Response intercept(Chain chain) throws IOException { 
     Request request = chain.request(); 
     Response response = chain.proceed(request); 
     ResponseBody body = response.body(); 
     // Only intercept JSON type responses and ignore the rest. 
     if (body != null && body.contentType() != null && body.contentType().subtype() != null && body.contentType().subtype().toLowerCase().equals("json")) { 
      String errorMessage = ""; 
      int errorCode  = 200; // Assume default OK 
      try { 
       BufferedSource source = body.source(); 
       source.request(Long.MAX_VALUE); // Buffer the entire body. 
       Buffer buffer = source.buffer(); 
       Charset charset = body.contentType().charset(Charset.forName("UTF-8")); 
       // Clone the existing buffer is they can only read once so we still want to pass the original one to the chain. 
       String json  = buffer.clone().readString(charset); 
       JsonElement obj = new JsonParser().parse(json); 
       // Capture error code an message. 
       if (obj instanceof JsonObject && ((JsonObject) obj).has("status")) { 
        errorCode = ((JsonObject) obj).get("status").getAsInt(); 
       } 
       if (obj instanceof JsonObject && ((JsonObject) obj).has("message")) { 
        errorMessage= ((JsonObject) obj).get("message").getAsString(); 
       } 
      } catch (Exception e) { 
       Log.e(TAG, "Error: " + e.getMessage()); 
      } 
      // Check if status has an error code then throw and exception so retrofit can trigger the onFailure callback method. 
      // Anything above 400 is treated as a server error. 
      if(errorCode > 399){ 
       throw new Exception("Server error code: " + errorCode + " with error message: " + errorMessage); 
      } 
     } 

     return response; 
    }