【发布时间】:2012-05-09 11:18:05
【问题描述】:
使用此代码时出现 OutOfMemory 异常:
class ApiTask extends AsyncTask<URI, Void, String> {
private Exception exception;
protected void onPreExecute() {
dialog = ProgressDialog.show(DownloadedActivity.this, "",
"Contacting Server...", true);
}
protected String doInBackground(URI... uri) {
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
try {
request.setURI(uri[0]);
return client.execute(request, new BasicResponseHandler());
} catch (Exception e) {
e.printStackTrace();
}
return "Error";
} catch (Exception e) {
this.exception = e;
return "Error";
}
}
@Override
protected void onPostExecute(String result) {
dialog.dismiss();
processJSON(result);
updateListView();
result = null;
System.gc();
}
}
当我在刷新方法中第二次运行此代码时发生错误,这使我怀疑内存泄漏。响应是一个大型 JSON 对象。我希望找出我做错了什么我尝试了一些事情,但它看起来像响应留在内存中。
这里是 logcat 错误:
05-09 13:45:13.764: E/AndroidRuntime(2438): Uncaught handler: thread AsyncTask #2 exiting due to uncaught exception
05-09 13:45:13.784: E/AndroidRuntime(2438): java.lang.RuntimeException: An error occured while executing doInBackground()
05-09 13:45:13.784: E/AndroidRuntime(2438): at android.os.AsyncTask$3.done(AsyncTask.java:200)
05-09 13:45:13.784: E/AndroidRuntime(2438): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
05-09 13:45:13.784: E/AndroidRuntime(2438): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
05-09 13:45:13.784: E/AndroidRuntime(2438): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
05-09 13:45:13.784: E/AndroidRuntime(2438): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
05-09 13:45:13.784: E/AndroidRuntime(2438): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
05-09 13:45:13.784: E/AndroidRuntime(2438): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
05-09 13:45:13.784: E/AndroidRuntime(2438): at java.lang.Thread.run(Thread.java:1096)
05-09 13:45:13.784: E/AndroidRuntime(2438): Caused by: java.lang.OutOfMemoryError
05-09 13:45:13.784: E/AndroidRuntime(2438): at java.lang.String.<init>(String.java:513)
05-09 13:45:13.784: E/AndroidRuntime(2438): at org.apache.http.util.CharArrayBuffer.toString(CharArrayBuffer.java:261)
05-09 13:45:13.784: E/AndroidRuntime(2438): at org.apache.http.util.EntityUtils.toString(EntityUtils.java:141)
05-09 13:45:13.784: E/AndroidRuntime(2438): at org.apache.http.util.EntityUtils.toString(EntityUtils.java:146)
05-09 13:45:13.784: E/AndroidRuntime(2438): at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:76)
05-09 13:45:13.784: E/AndroidRuntime(2438): at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:59)
05-09 13:45:13.784: E/AndroidRuntime(2438): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:657)
05-09 13:45:13.784: E/AndroidRuntime(2438): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627)
05-09 13:45:13.784: E/AndroidRuntime(2438): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:616)
05-09 13:45:13.784: E/AndroidRuntime(2438): at com.nelissen.couchforwarder.couch.DownloadedActivity$ApiTask.doInBackground(DownloadedActivity.java:382)
05-09 13:45:13.784: E/AndroidRuntime(2438): at com.nelissen.couchforwarder.couch.DownloadedActivity$ApiTask.doInBackground(DownloadedActivity.java:1)
05-09 13:45:13.784: E/AndroidRuntime(2438): at android.os.AsyncTask$2.call(AsyncTask.java:185)
05-09 13:45:13.784: E/AndroidRuntime(2438): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
05-09 13:45:13.784: E/AndroidRuntime(2438): ... 4 more
【问题讨论】:
-
请提供您的
processJSON方法的代码 - 如果其中有问题,很容易进入无限递归。 -
请求返回的字符串大小约为6mb,我认为问题出在那儿。当存在 OutOfMemory 错误时,甚至不会调用 processJson。哦,我忘了添加这个错误只发生在堆大小为 24mb 的设备上。生病检查它是否在不处理时崩溃。
-
它在 AsyncTask 而不是处理过程中崩溃,我通过删除解析进行了检查。我添加了 logcat
-
顺便说一句,您绝对不应该在 UI 线程上处理 omghuge JSON 回复,将其保留在 AsyncTask 中 - 并切换到可以读取流而不是读取流的 JSON 解析器Android 中包含的只吃整个
Strings 的蹩脚的。 -
好的,因此更改为流应该可以解决内存问题。但我不明白的是,为什么在 AsyncTask 完成并且 parseJSON 完成后,String 仍保留在内存中。
标签: android android-asynctask httpclient out-of-memory