Android AsyncTask 内存泄漏 [英] Android AsyncTask memory leaks

查看:23
本文介绍了Android AsyncTask 内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里阅读了一些问题,在 Internet 上阅读了一些文章,但是关于 AsyncTask 中的内存泄漏问题我不清楚.拜托,你能给我一个建议吗?
让我们考虑一些情况:

1) AsyncTask 是一个内部类
我编写了 MyAsyncTask 以从 MyActivity 代码(不是静态类)中的服务器(<1 KB)下载小数据.它将存储对 MyActivity 实例的隐式引用.如果我将启动 MyAsyncTask.execute(),则 MyActivity 实例不能被垃圾收集,直到此 AsyncTask 完成.因此,如果我在 AsyncTask 执行期间旋转屏幕,那么旧的 MyActivity 实例将在内存中 - 这是内存泄漏.
我决定做什么:由于我要下载的数据的大小,我将在 MyActivity 的 onDestroy() 方法中取消我的 AsyncTask.这样,我就有了MyActivity的这样的代码:

I read some questions here, some articles in Internet, but the question about memory leaks in AsyncTask isn't clear for me. Please, can you give me an advice?
Let's consider some situations:

1) AsyncTask is an inner class
I write MyAsyncTask for downloading small data from the server (<1 KB) in MyActivity code (not as static class). It will store an implicit reference to MyActivity instance. And if i'll start MyAsyncTask.execute(), then MyActivity instance cannot be Garbage Collected, until this AsyncTask will finish. So, if I'll rotate the screen during AsyncTask executing, then old MyActivity instance will be in memory - and it is memory leak.
What I decided to do: because of size of my data for downloading, I will cancel my AsyncTask in onDestroy() method in MyActivity. In this way, I have such code of MyActivity:

public class MyActivity extends Activity {

//views and constants
private MyAsyncTask air;
private ProgressDialog progressDialog;

protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.account_info_layout);
    progressDialog = new ProgressDialog(this);
    //findViewById, etc.

}   

@Override
protected void onStart() {
    super.onStart();
    air = new MyAsyncTask();
    air.execute();
}

@Override
protected void onDestroy() {
    if (air.getStatus() == AsyncTask.Status.RUNNING) {
        air.cancel(true);
    }
    air = null;
    super.onDestroy();
}


class MyAsyncTask extends AsyncTask<Void, Void, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        UserData.refreshTimer();
        if (!progressDialog.isShowing())
            progressDialog.show();
    }


    @Override
    protected String doInBackground(Void... params) {
        //GET request
        return result;      
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        //handle results
        progressDialog.dismiss();
    }
}

}


因此,如果我的活动实例被销毁,我会取消异步任务,并在 onStart() 中创建新实例.它会产生内存泄漏,还是会因为 progressDialog 实例而产生 IllegalArgumentException/NullPointerException?我想,它不会产生任何异常,因为如果我取消 AsyncTask,则不会调用 onPostExecute().

2) 自己文件中的 AsyncTask
下一种情况是当我在其他文件中编写 MyAsyncTask 并传入构造函数 Context 实例时.如果我将 Context 存储为 WeakReference,这种方法会产生内存泄漏吗?在调用 Activity 时取消 onDestroy() 方法中的 AsyncTask 以避免在 onPostExecute() 方法期间出现 IllegalArgumentException/NullPointerException 是否正确?或者,避免这些异常的其他方法是检查我的 Context 变量是否为空.

其他方法: 我听说过 Otto 库,关于使用保留的 Fragment,但现在我想了解这些问题.如果有人知道 - 请回答.


So, if my activity instance is destroyed, I cancel my async task, and create new instance in onStart(). Will it produce memory leaks, or can it produce IllegalArgumentException/NullPointerException because of progressDialog instance? I suppose, it will not produce any exceptions, because if I cancel the AsyncTask, onPostExecute() will not be called.

2) AsyncTask in own file
The next case is when I write MyAsyncTask in other file, and pass in constructor Context instance. Will such approach produce memory leaks, if I'll store Context as WeakReference? And is it correct idea to cancel AsyncTask in onDestroy() method in calling Activity to avoid IllegalArgumentException/NullPointerException during onPostExecute() method? Or, other way to avoid these exceptions is to check my Context variable for null.

Other approaches: I've heard about Otto library, about using retained Fragments, but now I want to understand these questions. If somebody knows - please, answer.

推荐答案

  1. 取消是解决内存泄漏的好方法.不过,您可能需要考虑在 onStop 中取消,因为您在 onStart 中设置了一个新任务.您可能希望将此与取消 onStop 中的 progressDialog 结合起来,因为您要取消任务.

  1. Cancelling is a good way to solve your memory leak. You might want to consider cancelling in onStop though, since you set up a new task in onStart. You might want to combine this with dismissing the progressDialog in onStop, since you're cancelling the task.

如果取消任务,不会造成内存泄漏.如果不这样做,可能会导致临时内存泄漏.例如,您可以通过使用 context.getApplicationContext() 而不是普通的 getContext/this (Activity) 构造新的 Java 文件来解决该问题.然后它不会绑定到活动而是绑定到应用程序(应用程序在方向更改后仍然存在).但是,您将无法访问 onPostExecute() 中的对话框.相反,如果需要,您可以使用对侦听器的回调.使活动实现侦听器(并在停止时将其分离).但取消也是一种很好的方法.

If you cancel the task, you will not cause a memory leak. If you don't, you might cause a temporary memory leak. You could for example solve that by constructing the new Java file with a context.getApplicationContext() instead of normal getContext / this (Activity). Then it will not be tied to the activity but to the application (the application survives orientation change). You however won't be able to access the dialog in onPostExecute(). Instead you could use a callback to a listener if you want. Make the activity implement the listener (and detach it onStop). But cancelling is a fine approach as well.

这篇关于Android AsyncTask 内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆