响应代码304和200时排空exception错误

玩Volley库的时候,我注意到在做一个POST JsonObjectRequest ,如果服务器返回一个代码304或者200,而响应中没有数据(response.data) ,那么Volley把它解释为错误响应,而不是成功。

我设法通过在类JsonObjectRequest.java中的Response<JSONObject> parseNetworkResponse(NetworkResponse response)方法中添加几行代码来解决此问题。

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

这是这个问题的最佳解决scheme吗?

谢谢!

编辑

检查类BasicNetwork.java我意识到,Volley通过询问httpResponse.getEntity() != null检查响应是否没有数据。

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

但问题仍然是当Volley尝试在parseNetworkResponse方法中使用response.data == new byte[0]创build新string时发生的JSONException。

Solutions Collecting From Web of "响应代码304和200时排空exception错误"

米格尔 – 这种方法不只是如果它的成功响应调用?

对于所有状态码<200或状态码> 200,volley调用parseNetworkError(VolleyError volleyError)而不是parseNetworkResponse(NetworkResponse响应)方法。 看这里 –

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

行号-118-120

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

和相应的catch块行号 – 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); } } 

如果你想覆盖这个行为,你可以在BasicNetwork.java-> performRequest方法中添加你的状态码特定的实现。

编辑:所以它不是因为状态码,而是因为空的响应。 那么我认为你正在做正确的事情实现你的自定义请求类。 Volley提供了一些预定义的stream行types的易用性请求,但是您可以随时创build自己的。 而不是一个基于状态代码的实现,我宁愿简单地检查下列string是否为空之前,反序列化它 –

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

**没有testing过,但你明白了:)