【问题标题】:OutOfMemory on AsyncTask in AndroidAndroid 中 AsyncTask 上的 OutOfMemory
【发布时间】: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


【解决方案1】:

我发现 AsyncTask 和 Activity 有点“松散地联系在一起”......所以也许 AsyncTask 不完全......死了!哈哈:D

尝试阅读此链接:Android AsyncTask for Long Running Operations

无论如何,在我的代码 onRefresh 中我都杀了他们!

public void onRefresh(View view){ // this is a method inside the Activity about to be killed            
    downloadXmlTaskObject = null; // Garbage Collectible 
    finish();                // Finish the Activity
    Intent intent = getIntent(); // get the intent of the Activity
    startActivity(intent);  // and Create a new Activity        
}

我不知道它是否符合您的要求..您可以创建一个 Activity 仅用于下载或解析等目的。然后将它们都杀死! 祝你好运! ^_^

【讨论】:

    【解决方案2】:

    我确信这是由于您在代码中编写的句子:

    return client.execute(request, new BasicResponseHandler());  // inside doInBackground
    

    我建议您为此创建另一个 AsyncTask 并在 onPostExecute() 方法中执行这个新的 AsyncTask。

    另一个可能是由于processJSON(result);,这可能是一个耗时的过程。

    【讨论】:

    • 我不明白为什么这样可以解决问题?
    猜你喜欢
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多