views:

565

answers:

3

I read a lot on how to save my instance state or how to deal with my activity getting destroyed during screen rotation.

There seem to be a lot of possibilities but I haven't figured out which one works best for retrieving results of an AsyncTask.

I have some AsyncTasks that are simply started again and call the isFinishing() method of the activity and if the activity is finishing they wont update anything.

The problem is that I have one Task that does a request to a web service that can fail or succeed and restarting the task would result in a financial loss for the user.

How would you solve this? What are the advantages or disadvantages of the possible solutions?

+2  A: 

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.

Jim Blackler
But that will prevent the Activity from changing the layout. And therefore forces the user to use his device in a specific orientation dictated by your application and not by his needs.
Janusz
@Janusz, it doesn't do that. The Activity is reoriented to the landscape/portrait dimensions and redrawn by the phone. It just stops it resetting the Activity, calling onCreate() etc. This is if you are using a general layout for all dimensions (as you should in my opinion).
Jim Blackler
why isn't that the default? Then all the activity killing problems would never happen? I always was suspicious why this is neccessary
Janusz
this is great :) thanks this hint was missing in all the posts on the issue... Why isn't that a default...
Janusz
Using this technique prevents you from easily using configuration specific resources. For instance, if you want your layout or drawables or strings or whatever to be different in portrait and landscapes, you'll want the default behavior. Overriding the config change should only be done in very specific cases (a game, a web browser, etc.) and not out of laziness or convenience because you are constraining yourself.
Romain Guy
Well that's just it, Romain. "if you want your layout or drawables or strings or whatever to be different in portrait and landscapes, you'll want the default behavior", I believe that is a much rarer use case than you envisage. What you call "very specific cases" is most developers I believe. Using relative layouts that work in all dimensions is best practice and it's not that hard. Talk of laziness is highly misguided, these techniques are to improve user experience not reduce development time.
Jim Blackler
I always build my UserInterface in a way that works in landscape and portrait. It is less work for me if there are changes in the layout later on and I haven't encountered a case where it doesn't works yet. Therefor I think the not destroying the activity would be a very reasonable default behaviour.
Janusz
I have found that this works perfect for LinearLayout, but when using RelativeLayout it does not redraw the layout correctly when switching to landscape mode (at least not on the N1). See this questions: http://stackoverflow.com/questions/2987049/how-to-refresh-an-android-relativelayout-when-orientation-changes-without-restart
+2  A: 

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.

Arhimed
+4  A: 

You can check out how I handle AsyncTasks and orientation change 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 onRetaingNonConfigurationInstance() to pass your AsyncTask to the new Activity (be careful about not leaking the previous Activity this way though.)

Romain Guy