我在这里读了一些问题,在互联网上有一些文章,但是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库,但现在我想了解这些问题。如果有人知道 - 请回答。
答案 0 :(得分:6)
取消是解决内存泄漏问题的好方法。您可能要考虑在onStop中取消,因为您在onStart中设置了一个新任务。 您可能希望将此与在onStop中解除progressDialog相结合,因为您正在取消该任务。
如果取消该任务,则不会导致内存泄漏。如果不这样做,可能会导致临时内存泄漏。例如,您可以通过使用context.getApplicationContext()而不是正常的getContext / this(Activity)构造新的Java文件来解决这个问题。然后它不会与活动相关联,而是与应用程序相关联(应用程序在方向更改后仍然存在)。但是,您将无法访问onPostExecute()中的对话框。相反,如果需要,您可以使用回调来监听。使活动实现监听器(并将其分离到onStop)。但取消也是一种很好的方法。
答案 1 :(得分:0)
通过取消异步任务的方式并不意味着它将立即被取消。 我建议您切换到Intent服务,处理程序,或者尽可能切换到RXJava。
与异步任务不同,在异步任务中您可能需要嵌套异步任务来执行多个执行,而使用RXJava,则可以将这些执行链接起来,应用过滤器和不同的转换,然后可以在工作线程上运行该代码。