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();
}
}
}
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.