我在Android平台上使用Google Volley.我遇到一个问题,其中error
参数in onErrorResponse
返回null networkResponse
对于我正在使用的RESTful API,我需要确定Http状态代码,它经常以401(SC_UNAUTHORIZED)或500(SC_INTERNAL_SERVER_ERROR)到达,我偶尔可以检查通过:
final int httpStatusCode = error.networkResponse.statusCode; if(networkResponse == HttpStatus.SC_UNAUTHORIZED) { // Http status code 401: Unauthorized. }
这会抛出一个NullPointerException
因为networkResponse
null.
如何确定函数中的Http状态代码onErrorResponse
?
或者,我如何确保error.networkResponse
非空onErrorResponse
?
或者,我如何确保onErrorResponse中的error.networkResponse为非null?
我的第一个想法是检查对象是否为空.
@Override public void onErrorResponse(VolleyError error) { NetworkResponse networkResponse = error.networkResponse; if (networkResponse != null && networkResponse.statusCode == HttpStatus.SC_UNAUTHORIZED) { // HTTP Status Code: 401 Unauthorized } }
或者,您也可以尝试通过扩展Request
类和覆盖来获取状态代码parseNetworkResponse
.
例如,如果扩展抽象Request
类
public class GsonRequestextends Request { ... private int mStatusCode; public int getStatusCode() { return mStatusCode; } ... @Override protected Response parseNetworkResponse(NetworkResponse response) { mStatusCode = response.statusCode; try { Log.d(TAG, "[raw json]: " + (new String(response.data))); Gson gson = new Gson(); String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); return Response.success(gson.fromJson(json, mClazz), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JsonSyntaxException e) { return Response.error(new ParseError(e)); } } ... }
或者,如果您正在使用已扩展抽象Request
类的工具箱类之一并且您不想混淆实现parseNetworkResponse(NetworkResponse networkResponse)
,请继续覆盖该方法,但通过以下方式返回超级实现super.parseNetworkResponse(networkResponse)
例如 StringResponse
public class MyStringRequest extends StringRequest { private int mStatusCode; public MyStringRequest(int method, String url, Listenerlistener, ErrorListener errorListener) { super(method, url, listener, errorListener); } public int getStatusCode() { return mStatusCode; } @Override protected Response parseNetworkResponse(NetworkResponse response) { mStatusCode = response.statusCode; return super.parseNetworkResponse(response); } }
用法:
public class myClazz extends FragmentActivity { private Request mMyRequest; ... public void makeNetworkCall() { mMyRequest = new MyNetworkRequest( Method.GET, BASE_URL + Endpoint.USER, new Listener() { @Override public void onResponse(String response) { // Success } }, new ErrorListener() { @Override public void onErrorResponse(VolleyError error) { if (mMyRequest.getStatusCode() == 401) { // HTTP Status Code: 401 Unauthorized } } }); MyVolley.getRequestQueue().add(request); }
当然,也可以使用覆盖方法内联的选项
public class MyClazz extends FragmentActivity { private int mStatusCode; ... public void makeNetworkCall() { StringRequest request = new StringRequest( Method.GET, BASE_URL + Endpoint.USER, new Listener() { @Override public void onResponse(String response) { // Success } }, new ErrorListener() { @Override public void onErrorResponse(VolleyError error) { if (mStatusCode == 401) { // HTTP Status Code: 401 Unauthorized } } }) { @Override protected Response parseNetworkResponse(NetworkResponse response) { mStatusCode = response.statusCode; return super.parseNetworkResponse(response); } }; MyVolley.getRequestQueue.add(request); }
更新:
HttpStatus
已弃用.请HttpURLConnection
改用.见链接.
事实证明,如果没有修改Google Volley代码,则无法保证error.networkResponse为非null,因为Volley中的一个错误会在设置之前抛出BasicNetwork.java(134)中的NoConnectionError
Http状态代码401(HttpStatus.SC_UNAUTHORIZED
)的异常.的价值networkResponse
.
在这种情况下,我们的解决方案不是修复Volley代码,而是修改Web Service API以HttpStatus.SC_FORBIDDEN
针对特定情况发送Http Error Code 403().
对于此Http状态代码,error.networkResponse
Volley错误处理程序中的值为非null : public void onErrorResponse(VolleyError error)
. 而且,error.networkResponse.httpStatusCode
正确回报HttpStatus.SC_FORBIDDEN
.
Rperryng关于扩展课程的建议Request
可能提供了一个解决方案,并且是一个创造性和优秀的想法.非常感谢您的详细示例.我发现我们案例的最佳解决方案是使用解决方法,因为我们很幸运能够控制Web服务API.
如果我无法在服务器上进行简单的更改,我可能会选择将Volley代码修复到BasicNetwork.java中的一个位置.
Volley支持HTTP 401 Unauthorized响应.但是这个响应必须包括"WWW-Authenticate"头字段.
没有此标头,401响应会导致"com.android.volley.NoConnectionError: java.io.IOException: No authentication challenges found"
错误.
有关更多详细信息,请访问:https://stackoverflow.com/a/25556453/860189
如果您使用第三方API并且无权更改响应标头,则可能会考虑实施您自己的HttpStack,因为HurlStack会抛出此异常.或者更好,使用OkHttpStack作为HttpStack.