【问题标题】:Volley exception error when response code 304 and 200响应代码 304 和 200 时的 Volley 异常错误
【发布时间】:2014-02-22 11:18:03
【问题描述】:

在使用 Volley 库时,我注意到在进行 POST JsonObjectRequest 时,如果服务器在响应 (response.data) 中返回没有数据的代码 304 或 200,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));
    }
}

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

谢谢!

编辑

检查 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] 创建新字符串时发生的 JSONException。

【问题讨论】:

    标签: android request android-volley jsonobject http-status-code-304


    【解决方案1】:

    Miguel- 不是只有在成功响应时才调用此方法吗?

    对于所有状态码 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();
       }
    

    以及对应的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 附带了一些预定义的流行类型的请求以方便使用,但您始终可以创建自己的请求。 而不是基于状态代码的实现,我宁愿在反序列化之前简单地检查以下字符串是否为空 -

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

    **尚未对此进行测试,但你明白了:)

    【讨论】:

    • 问题是代码200或代码304(未修改)没有返回数据时,我编辑了帖子。
    • 您使用的是什么版本的 volley。主分支android.googlesource.com/platform/frameworks/volley/+/master/… 没有任何会在没有响应数据的情况下引发错误的东西。相反,他们在这种情况下添加了一个 0 字节的响应。行号 106-112
    • 当您尝试从从 0 字节对象创建的字符串中创建 JSONObject 时,它会抛出 JSONException。
    • 是的,只是您的问题不是状态代码而是空响应。那么为什么有一个基于状态码而不是空响应的实现呢??
    猜你喜欢
    • 2013-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 1970-01-01
    • 2020-08-31
    • 1970-01-01
    • 2016-09-20
    相关资源
    最近更新 更多