在使用Volley库时,我注意到在进行POST时JsonObjectRequest,如果服务器返回的代码304或200没有响应中的数据(response.data),Volley会将其解释为错误响应,而不是成功。
JsonObjectRequest
(response.data)
我设法通过Response<JSONObject> parseNetworkResponse(NetworkResponse response)在类的方法中添加几行代码来解决该问题JsonObjectRequest.java。
Response<JSONObject> parseNetworkResponse(NetworkResponse response)
JsonObjectRequest.java
@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)); } }
这是解决此问题的最佳解决方案吗?
谢谢!
编辑
检查类时,BasicNetwork.java我意识到Volley通过询问是否检查响应是否没有数据httpResponse.getEntity() != null。
BasicNetwork.java
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尝试response.data == new byte[0]在parseNetworkResponse方法中使用创建新字符串时发生的JSONException。
response.data == new byte[0]
Miguel-仅在成功响应后才调用此方法吗?
对于所有状态代码<200或状态代码> 200,Volley调用parseNetworkError(VolleyError volleyError)而不是parseNetworkResponse(NetworkResponse response)方法。看这里 -
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(); }
和相应的捕获块行号-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方法内添加特定于状态码的实现。
编辑:所以它不是因为状态码而是因为响应为空。好吧,我认为您在实现自定义Request类方面做得正确。Volley随附了一些预定义的流行请求类型,以简化易用性,但您始终可以创建自己的请求。与其基于状态码的实现,不如直接反序列化之前检查以下字符串是否为空-
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)); }
**尚未测试过,但您明白了:)