我正在创建一个Android应用程序,它接受用户输入,尝试使用指定的输入建立与API URL的连接并检索数据并显示它。现在我已经能够完成上述所有工作,但是如果用户输入某些内容并且它不存在,我的应用程序可能会因为NPE(空指针异常)而崩溃。
我使用的API向我显示了可能发生的响应错误列表,但我不确定如何处理或实现将这些响应错误考虑在内的功能。
目前我的扩展 AsyncTask 类具有以下参数: String,Void,JSONObject ,以下代码是我在 doInBackground 方法中的代码
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
int statusCode = urlConnection.getResponseCode();
switch (statusCode) {
case 400:
return "Error 400 - Bad request.";
case 401:
return "Error 401 - Unauthorized request.";
}
我无法返回一个String,因为我的AsyncTask参数返回一个JSONObject。我可以改变它,所以它确实返回一个字符串,但我认为这不是处理响应错误的正确逻辑方式。
现在,如果API响应代码是404(找不到数据),我不希望应用程序崩溃,因为它无法返回JSONObject,而是我希望它继续下一个片段并显示最少的信息。
那么当我的方法返回JSONObject时,如何处理响应错误?
答案 0 :(得分:2)
你有几个选择(我说#1是你最好的选择)
1)创建一个自定义JSON对象,将状态代码从后台部分传送到UI(或其他调用线程)。然后检查从asynctask返回的JSON是否是“HTTP结果JSON”之一而不是正常结果。 (基本上从JSON中的后台处理中包装你的'exception'/ etc。并使用JSON传输你的返回消息,以便在任何一种情况下进行处理。)
2)你可以抛出一个异常(但我个人认为这是一个糟糕的设计,它通常更好地捕获异常,然后在onPostExecute()中处理它们(通过像#1这样的标志)
3)您可以在asyncTask之外的某处设置一个标志,以确定返回代码是什么(但这通常不是线程安全的。如果您的用户导致两个任务同时运行并且它们返回,则可能会很麻烦不同的顺序(或同时),你可能无法获得每个回报的'正确'值。)
4)你可以像https://stackoverflow.com/a/6312491/5673694那样做。但是有一个不好的问题和一个'ehh'问题......
糟糕的问题:她的实施有一个内存泄漏问题。 Java中的内部类在实例化时具有对其外部类实例的继承引用。这意味着,如果您的异步任务仍然在运行,那么您的父类/(活动最有可能)将无法收集垃圾,如果您因某种原因退出应用程序/电话进来/等等...所以你的应用程序可能会在很长一段时间内耗尽系统中的内存。 (无论你的asyncTask运行多长时间(无限可能))要解决此问题,请将内部类设为静态,并使用WeakRefernce<>到班级实例。 (这应该适用于Android中的所有内部类,它们与后台任务一起工作,例如处理程序等。)这个内存泄漏问题没有很好的记录,但存在,我们在MOOC中讨论我的博士顾问是教练和我是工作人员https://www.coursera.org/course/posacommunication
答案 1 :(得分:0)
当statusCode不是200时,您可以返回null:
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
int statusCode = urlConnection.getResponseCode();
if(statusCode!= 200){
return null;
}
然后在你的postExecute中你可以检查那个条件:
protected void onPostExecute(JSONObject result) {
if (result == null) {
// Inform the user something weird happened
}
else{
// Do your normal condition with your JSON object
}
您还可以尝试其他方法:您可以返回ArrayList:
,而不是返回JSON对象 ArrayList<Object> result = new ArrayList<Object>();
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
int statusCode = urlConnection.getResponseCode();
switch (statusCode) {
case 200:
// Your code to build your JSON object
JSONObject yourJsonObject = ...
result.add("Ok");
result.add(yourJsonObject);
break;
case 400:
result.add("Error 400 - Bad request.");
result.add(null);
break;
case 401:
result.add("Error 401 - Unauthorized request.");
result.add(null);
break;
}
然后在你的postExecute中检查ArrayList对象:
protected void onPostExecute(ArrayList<Object> result) {
String message = (String) result.get(0);
JSONObject yourJsonObject = (JSONObject) result.get(1);
if (result == yourJsonObject) {
// Inform the user something weird happened
// Example: Toast the message
}
else{
// Do your normal condition with your JSON object
}