Android:如何使用 Volley 处理来自服务器的消息错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21867929/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android: How handle message error from the server using Volley?
提问by FlavienBert
I am using Volleyfor my Android app to fetch data from my server. It works well except when handling the error from my server. My server sends this response when there is a mistake:
我在我的 Android 应用程序中使用Volley从我的服务器获取数据。除非处理来自我的服务器的错误,否则它运行良好。当出现错误时,我的服务器会发送此响应:
{
"status": 400,
"message": "Errors (2): A name is required- Julien is already used. Not creating."
}
My goal is to get the message and then display it in a Toast
. I followed some sample for how to do this, but it doesn't work.
我的目标是获取消息,然后将其显示在Toast
. 我遵循了一些示例来了解如何执行此操作,但它不起作用。
There is my error listener :
有我的错误侦听器:
public void onErrorResponse(VolleyError error) {
int statusCode = error.networkResponse.statusCode;
NetworkResponse response = error.networkResponse;
Log.d("testerror",""+statusCode+" "+response.data);
// Handle your error types accordingly.For Timeout & No connection error, you can show 'retry' button.
// For AuthFailure, you can re login with user credentials.
// For ClientError, 400 & 401, Errors happening on client side when sending api request.
// In this case you can check how client is forming the api and debug accordingly.
// For ServerError 5xx, you can do retry or handle accordingly.
if( error instanceof NetworkError) {
} else if( error instanceof ClientError) {
} else if( error instanceof ServerError) {
} else if( error instanceof AuthFailureError) {
} else if( error instanceof ParseError) {
} else if( error instanceof NoConnectionError) {
} else if( error instanceof TimeoutError) {
}
showProgress(false);
mPasswordView.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
}
And there the result of my debugger :testerror﹕ 400 [B@430b8d60
我的调试器的结果是:testerror:400 [B@430b8d60
EDIT:Moreover my error.getMessage() is null.
编辑:此外,我的 error.getMessage() 为空。
So I don't understand why my variable response.data is not the response from my server.
所以我不明白为什么我的变量 response.data 不是来自我的服务器的响应。
If someone know how I can get the message from my server it's will be cool.
如果有人知道我如何从我的服务器获取消息,那就太酷了。
Thx,
谢谢,
回答by Submersed
I've implemented something similar to this, and it's relatively simple. Your log message is printing out what looks like gibberish, because response.data
is really a byte array - not a String
. Also, a VolleyError
is really just an extended Exception
, so Exception.getMessage() likely wouldn't return what you are looking for unless you override the parsing methods for parsing your VolleyError
in your extended Request
class. A really basic way to handle this would be to do something like:
我已经实现了类似的东西,它相对简单。您的日志消息正在打印出看起来像乱码的内容,因为response.data
它实际上是一个字节数组 - 而不是String
. 此外, aVolleyError
实际上只是一个扩展Exception
,因此Exception.getMessage() 可能不会返回您要查找的内容,除非您覆盖用于解析VolleyError
扩展Request
类中的解析方法。处理此问题的一种非常基本的方法是执行以下操作:
//In your extended request class
@Override
protected VolleyError parseNetworkError(VolleyError volleyError){
if(volleyError.networkResponse != null && volleyError.networkResponse.data != null){
VolleyError error = new VolleyError(new String(volleyError.networkResponse.data));
volleyError = error;
}
return volleyError;
}
}
If you add this to your extended Request
classes, your getMessage()
should at least not return null. I normally don't really bother with this, though, since it's easy enough to do it all from within your onErrorResponse(VolleyError e)
method.
如果将此添加到扩展Request
类中,则getMessage()
至少不应返回 null。不过,我通常不会真正为此烦恼,因为在您的onErrorResponse(VolleyError e)
方法中很容易做到这一切。
You should use a JSON library to simplify things -- I use Gsonfor example or you could use Apache's JSONObject
s which shouldn't require an additional external library. The first step is to get the response JSON sent from your server as a String
(in a similar fashion to what I just demonstrated), next you can optionally convert it to a JSONObject(using either apache's JSONObject
s and JsonArray
s, or another library of your choice) or just parse the String
yourself. After that, you just have to display the Toast
.
您应该使用 JSON 库来简化事情——例如,我使用Gson,或者您可以使用 Apache 的JSONObject
s ,它不需要额外的外部库。第一步是获取从您的服务器发送的响应 JSON String
(以类似于我刚刚演示的方式),接下来您可以选择将其转换为JSONObject(使用 apache 的JSONObject
s 和JsonArray
s,或您选择的另一个库) 或者只是解析String
你自己。之后,您只需要显示Toast
.
Here's some example code to get you started:
下面是一些示例代码,可帮助您入门:
public void onErrorResponse(VolleyError error) {
String json = null;
NetworkResponse response = error.networkResponse;
if(response != null && response.data != null){
switch(response.statusCode){
case 400:
json = new String(response.data);
json = trimMessage(json, "message");
if(json != null) displayMessage(json);
break;
}
//Additional cases
}
}
public String trimMessage(String json, String key){
String trimmedString = null;
try{
JSONObject obj = new JSONObject(json);
trimmedString = obj.getString(key);
} catch(JSONException e){
e.printStackTrace();
return null;
}
return trimmedString;
}
//Somewhere that has access to a context
public void displayMessage(String toastString){
Toast.makeText(context, toastString, Toast.LENGTH_LONG).show();
}
回答by Mina Fawzy
try this class to handle all erros
试试这个类来处理所有的错误
public class VolleyErrorHelper {
/**
* Returns appropriate message which is to be displayed to the user
* against the specified error object.
*
* @param error
* @param context
* @return
*/
public static String getMessage (Object error , Context context){
if(error instanceof TimeoutError){
return context.getResources().getString(R.string.timeout);
}else if (isServerProblem(error)){
return handleServerError(error ,context);
}else if(isNetworkProblem(error)){
return context.getResources().getString(R.string.nointernet);
}
return context.getResources().getString(R.string.generic_error);
}
private static String handleServerError(Object error, Context context) {
VolleyError er = (VolleyError)error;
NetworkResponse response = er.networkResponse;
if(response != null){
switch (response.statusCode){
case 404:
case 422:
case 401:
try {
// server might return error like this { "error": "Some error occured" }
// Use "Gson" to parse the result
HashMap<String, String> result = new Gson().fromJson(new String(response.data),
new TypeToken<Map<String, String>>() {
}.getType());
if (result != null && result.containsKey("error")) {
return result.get("error");
}
} catch (Exception e) {
e.printStackTrace();
}
// invalid request
return ((VolleyError) error).getMessage();
default:
return context.getResources().getString(R.string.timeout);
}
}
return context.getResources().getString(R.string.generic_error);
}
private static boolean isServerProblem(Object error) {
return (error instanceof ServerError || error instanceof AuthFailureError);
}
private static boolean isNetworkProblem (Object error){
return (error instanceof NetworkError || error instanceof NoConnectionError);
}