8

Herumspielen mit der Volley-Bibliothek, bemerkte ich, dass bei der Erstellung eines POST JsonObjectRequest, wenn der Server einen Code 304 oder 200 ohne Daten in der Antwort (response.data) zurückgibt, interpretiert Volley es als Fehlerreaktion statt eines Erfolges.Volley Ausnahmefehler, wenn Antwortcode 304 und 200

Ich es zu lösen, indem Sie ein paar Zeilen Code in der Methode Response<JSONObject> parseNetworkResponse(NetworkResponse response) in der Klasse JsonObjectRequest.java hinzufügen.

@Override 
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) { 
    try { 
     if (!response.notModified) {// Added for 304 response 
      String jsonString = new String(response.data, 
        HttpHeaderParser.parseCharset(response.headers)); 
      return Response.success(new JSONObject(jsonString), 
        HttpHeaderParser.parseCacheHeaders(response)); 
     } else // Added for 304 response 
      return Response.success(new JSONObject(),HttpHeaderParser.parseCacheHeaders(response)); 
    } catch (UnsupportedEncodingException e) { 
     Log.v("Volley", "UnsupportedEncodingException " + response.statusCode); 
     if (response.statusCode == 200)// Added for 200 response 
      return Response.success(new JSONObject(), HttpHeaderParser.parseCacheHeaders(response)); 
     else 
      return Response.error(new ParseError(e)); 
    } catch (JSONException je) { 
     Log.v("Volley", "JSONException " + response.statusCode); 
     if (response.statusCode == 200)// Added for 200 response 
      return Response.success(new JSONObject(),HttpHeaderParser.parseCacheHeaders(response)); 
     else 
      return Response.error(new ParseError(je)); 
    } 
} 

Ist es die beste Lösung für dieses Problem?

Danke!

EDIT

Überprüfung der Klasse BasicNetwork.java erkannte ich, dass Volley prüft, ob eine Antwort keine Daten durch, wenn httpResponse.getEntity() != null zu fragen.

// Some responses such as 204s do not have content. We must check. 
    if (httpResponse.getEntity() != null) { 
     responseContents = entityToBytes(httpResponse.getEntity());   
    } else {// Add 0 byte response as a way of honestly representing a 
    // no-content request. 
     responseContents = new byte[0]; 
    } 

Aber das Problem ist immer noch die JSONException das auftritt, wenn Volley versucht, eine neue Zeichenfolge mit response.data == new byte[0] im parseNetworkResponse Methode zu erstellen.

Antwort

6

Miguel- Wird diese Methode nicht nur aufgerufen, wenn es eine Erfolgsantwort ist?

Für alle Statuscodes < 200 oder Statuscode> 200 volley ruft parseNetworkError (VolleyError volleyError) anstelle von parseNetworkResponse (NetworkResponse response) auf. Schau mal hier -

https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/volley/toolbox/BasicNetwork.java

Zeilennummer -118-120

if (statusCode < 200 || statusCode > 299) { 
       throw new IOException(); 
    } 

und die entsprechende Fangblock Zeilennummer - 128 -151

catch (IOException e) { 
      int statusCode = 0; 
      NetworkResponse networkResponse = null; 
      if (httpResponse != null) { 
       statusCode = httpResponse.getStatusLine().getStatusCode(); 
      } else { 
       throw new NoConnectionError(e); 
      } 
      VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl()); 
      if (responseContents != null) { 
       networkResponse = new NetworkResponse(statusCode, responseContents, 
         responseHeaders, false); 
       if (statusCode == HttpStatus.SC_UNAUTHORIZED || 
         statusCode == HttpStatus.SC_FORBIDDEN) { 
        attemptRetryOnException("auth", 
          request, new AuthFailureError(networkResponse)); 
       } else { 
        // TODO: Only throw ServerError for 5xx status codes. 
        throw new ServerError(networkResponse); 
       } 
      } else { 
       throw new NetworkError(networkResponse); 
      } 
     } 

Wenn Sie dieses Verhalten außer Kraft setzen möchten Sie können Ihre statuscode-spezifische Implementierung in BasicNetwork.java-> performRequest-Methode hinzufügen.

Edit: So ist es nicht wegen Statuscode, sondern wegen der leeren Antwort. Nun, ich denke, Sie tun das Richtige, um Ihre benutzerdefinierte Request-Klasse zu implementieren. Volley kommt mit ein paar vordefinierten beliebten Arten von Anfragen für die Benutzerfreundlichkeit, aber Sie können immer Ihre eigenen erstellen. Anstelle einer Statuscode basierten Implementierung ich würde eher einfach überprüfen, ob die folgende Zeichenfolge vor deserialzing es leer ist -

String jsonString = new String(response.data, 
       HttpHeaderParser.parseCharset(response.headers)); 
if (!jsonString .isEmpty()) { 
       return Response.success(new JSONObject(jsonString), 
       HttpHeaderParser.parseCacheHeaders(response)); 
} 
else { 
return Response.success(new JSONObject(), 
        HttpHeaderParser.parseCacheHeaders(response)); 
} 

** habe nicht getestet, aber Sie erhalten den Punkt :)

+0

Die Problem ist, wenn der Code 200 oder der Code 304 (nicht modifiziert) keine Daten zurückgeben, habe ich den Beitrag bearbeitet. – Miguel

+0

welche Version von Volley verwenden Sie. Der Master-Zweig https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/volley/toolbox/BasicNetwork.java hat nichts, was zu einem Fehler führen würde, wenn keine Daten vorhanden sind Antwort. Stattdessen haben sie in diesem Fall eine 0-Byte-Antwort hinzugefügt. Zeilennummer 106-112 – Gaurav

+0

Wenn Sie versuchen, ein JSONObject aus einem String zu erstellen, der aus einem 0-Byte-Objekt erstellt wurde, wird eine JSONException ausgelöst. – Miguel