I do use lots of AsyncTasks within Activities as private inner classes. One thing that puzzles me since the beginning is what context do I get within onPostExecute()?
If you look at the stripped down example shown below you can use getString() within onPostExecute(). What context is used for that call? The Activity may have changed during doInBackground (e.g. OrientationChange) so it can’t be that context.
Currently I patch the Activity context (task.context = this) and use that specific context (context.getString()).
My question: Is it save to use getString() within onPostExecute() of an Inner Class AsyncTask without using the context of the surrounding Activity?
Many thanks in advance.
public class MyActivity extends Activity {
/* package */ MyActivity context;
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
public MyAsyncTask(final MyActivity context) {
super();
this.context = context;
}
@Override
protected Cursor doInBackground(/* ... */) {
// ...
}
@Override
protected void onPostExecute(/* ... */) {
if (context != null) {
// Currently I do use that
String s = context.getString(R.string.mytext);
context.task = null;
}
// Would this be save?
String s2 = getString(R.string.mytext);
}
@Override
protected void onPreExecute (/* ... */) {
// ...
}
}
/* package */ MyAsyncTask task;
@Override
public void onCreate(final Bundle bundle) {
// ...
Bundle bundleExtras = getIntent().getExtras();
if (bundleExtras != null) {
task = (MyAsyncTask) getLastNonConfigurationInstance();
if (task != null) {
task.context = this;
// ...
} else {
task = new MyAsyncTask(this);
task.execute();
}
}
}
@Override
public Object onRetainNonConfigurationInstance() {
if (task != null) {
// ...
task.context = null;
}
return task;
}
}
No it’s not safe. Being an inner class in that activity your
MyAsyncTaskclass you’ll have a reference toMyActivitywhen it is created. So, ifMyActivityis killed for any reason (like rotation), in theonPostExecutecallback you’ll end up withMyAsyncTaskholding a reference of the killedMyActivityinstance.Using a reference to the
Activityit’s safer because you update that reference to always point to a valid instance ofMyActivity. Maybe you’ll also want to invalidate theActivitydirectly inonRetainNonConfigurationInstancewithnullto make sure you don’t touch it(if theMyAsyncTaskreaches theonPostExecuteuntil you setup theMyActivityagain) until you have a valid reference.