How to handle an AsyncTask during Screen Rotation?

You can check out how I handle AsyncTasks and orientation changes at code.google.com/p/shelves. There are various ways to do it, the one I chose in this app is to cancel any currently running task, save its state and start a new one with the saved state when the new Activity is created. It's easy to do, it works well and as a bonus it takes care of stopping your tasks when the user leaves the app.

You can also use onRetainNonConfigurationInstance() to pass your AsyncTask to the new Activity (be careful about not leaking the previous Activity this way though.)


This is the most interesting question I've seen regarding to Android!!! Actually I've been already looking for the solution during the last months. Still haven't solved.

Be careful, simply overriding the

android:configChanges="keyboardHidden|orientation"

stuff is not enough.

Consider the case when user receives a phone call while your AsyncTask is running. Your request is already being processed by server, so the AsyncTask is awaiting for response. In this moment your app goes in background, because the Phone app has just come in foreground. OS may kill your activity since it's in the background.


My first suggestion would be to make sure you actually need your activity to be reset on a screen rotation (the default behavior). Every time I've had issues with rotation I've added this attribute to my <activity> tag in the AndroidManifest.xml, and been just fine.

android:configChanges="keyboardHidden|orientation"

It looks weird, but what it does it hand off to your onConfigurationChanged() method, if you don't supply one it just does nothing other than re-measure the layout, which seems to be a perfectly adequate way of handling the rotate most of the time.


Why don't you always keep a reference to the current AsyncTask on the Singleton provided by Android?

Whenever a task starts, on PreExecute or on the builder, you define:

((Application) getApplication()).setCurrentTask(asyncTask);

Whenever it finishes you set it to null.

That way you always have a reference which allows you to do something like, onCreate or onResume as appropriated for your specific logic:

this.asyncTaskReference = ((Application) getApplication()).getCurrentTask();

If it's null you know that currently there is none running!

:-)


The most proper way to this is to use a fragment to retain the instance of the async task, over rotations.

Here is a link to very simple example making it easy to follow integrate this technique into your apps.

https://gist.github.com/daichan4649/2480065