AsyncTask and context leaking

Read Time 2 minutes

AsyncTask is mostly used as inner class of Activity or Fragment. For example:

public class SampleActivity extends Activity
{
private static SampleActivity instance;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);

new SampleTask().execute();
}

@Override
protected void onPause()
{
super.onPause();
instance = null;
}

@Override
protected void onResume()
{
super.onResume();
instance = this;
}

private class SampleTask extends AsyncTask
{
@Override
protected String doInBackground(Void… params)
{
// function calls
return “dummyResult”;
}

@Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);

if(SampleActivity.instance != null)
{
onResult(result);
}
}

}

private void onResult(String result)
{
// Update UI
}

}

The problem with the above approach is that as long as SampleTask is running, SampleActivity will not be garbage collected even after being stopped. SampleTask needs an instance of activity because it is declared inside the SampleActivity.

The right way to use AsyncTask inside Activity is to define it as static. Static members don’t need instance of the class so the activity will be garbage collected (after it is stopped) even though if task is running. To update the UI from task we need instance of the activity, and for that we can keep weakRefrence of activity inside the Asynctask. WeakRefrence allow the activity to be garbage collected once it is stopped. The above code can be re-written like this:

public class SampleActivity extends Activity
{
private static SampleTask task;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);

task = new SampleTask(this);
task.execute();
}
@Override
protected void onPause()
{
super.onPause();
if(task != null)
{
task.cancel(true);
task = null;
}
}
private static class SampleTask extends AsyncTask
{
WeakReference activityRef;

public SampleTask(SampleActivity activity)
{
activityRef = new WeakReference(activity);
}

@Override
protected String doInBackground(Void… params)
{
// function calls
return “dummyResult”;
}

@Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);

SampleActivity activity = activityRef.get();

if(activity != null)
{
activity.onResult(result);
}
}

}

private void onResult(String result)
{
// update UI
}

}

 

Leave a Comment

Your email address will not be published. Required fields are marked *