Android AsyncTask内存泄漏

时间:2017-09-18 07:23:43

标签: android memory-leaks android-asynctask

我在这里读了一些问题,在互联网上有一些文章,但是AsyncTask中关于内存泄漏的问题对我来说并不清楚。拜托,你能给我一个建议吗? 让我们考虑一些情况:

1)AsyncTask是一个内部类
我编写了MyAsyncTask,用于从MyActivity代码中的服务器(<1 KB)下载小数据(而非静态类)。它将存储对MyActivity实例的隐式引用。如果我将启动MyAsyncTask.execute(),那么MyActivity实例不能被Garbage Collected,直到此AsyncTask完成。因此,如果我在执行AsyncTask期间旋转屏幕,那么旧的MyActivity实例将在内存中 - 这是内存泄漏。
我决定做什么:由于我的数据大小下载,我将在MyActivity的onDestroy()方法中取消我的AsyncTask。这样,我就有了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存储,这种方法是否会产生内存泄漏?在onPostExecute()方法中调用Activity以避免IllegalArgumentException / NullPointerException,取消onDestroy()方法中的AsyncTask是否正确?或者,避免这些异常的其他方法是检查我的Context变量是否为空。

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

2 个答案:

答案 0 :(得分:6)

  1. 取消是解决内存泄漏问题的好方法。您可能要考虑在onStop中取消,因为您在onStart中设置了一个新任务。 您可能希望将此与在onStop中解除progressDialog相结合,因为您正在取消该任务。

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

答案 1 :(得分:0)

通过取消异步任务的方式并不意味着它将立即被取消。 我建议您切换到Intent服务,处理程序,或者尽可能切换到RXJava。

与异步任务不同,在异步任务中您可能需要嵌套异步任务来执行多个执行,而使用RXJava,则可以将这些执行链接起来,应用过滤器和不同的转换,然后可以在工作线程上运行该代码。