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

查看:96
本文介绍了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以避免onPostExecute()方法期间避免IllegalArgumentException/NullPointerException时取消onDestroy()方法中的AsyncTask是否正确?或者,避免这些异常的另一种方法是检查我的Context变量是否为null.

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


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. 取消是解决内存泄漏的好方法.不过,由于您在onStart中设置了新任务,因此您可能要考虑在onStop中取消. 您可能想将其与取消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()中访问该对话框.相反,您可以根据需要使用侦听器的回调.使活动实现侦听器(并在onStop上将其分离).但是取消也是一种很好的方法.

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天全站免登陆