tags:

views:

667

answers:

3

Hi,

I'm using an AsyncTask in my activity. Looks like:

public class MyActivity {
    private AsyncTask mTask;

    private void doSomethingCool() {
        mTask = new AsyncTask(...);
        mTask.execute();
    }

    @Override
    protected void onPause() { 
        super.onPause();

        // How do I let the task keep running if just rotating?
        if (isFinishing() == false) {
            ... 
        }
    }
}

So if the user is rotating the device, onPause() will get called, but I don't want to cancel the task just because of that. I know there's a way to tell the system to not actually destroy my activity on rotation, but is that recommended for this problem? Should I instead put the AsyncTask in a static global class that won't be bound to the Activity?

Thanks

+1  A: 

Before diving into the fun that is AsyncTask and orientation changes, let me first ask this - do you need to hold onto the AsyncTask in a variable? There are not many reasons that you need to do this, because AsyncTask has callbacks built-in, so you don't actually need to hold onto your AsyncTask (don't call him, he'll call you). Also, your AsyncTask should continue running even during an orientation change - it's in another thread, after all.

The only time I've had to hold onto AsyncTask was to fix a bug that occurs when you try to show a Dialog while the AsyncTask is running. There's a fix, but it's pretty nasty. There's a lot of discussion of that here, if that's the specific problem you're running into.

Daniel Lew
ok, in that case, I *don't* need to hold onto it. I'm running a login function over the network in the task. So I just need to get notified when it's complete. I don't understand what will happen though if the user destroys the activity, and then the task completes - what will it "call back"? Will it still try to touch the now-destroyed activity?
Mark
+2  A: 

This adds onto Daniel's answer, but is more characters than I can fit in a comment.

More often than not, when I'm using an AsyncTask, I want a dialog spinning, and dealing with that is absurd. You have to do something very much like the solution in the thread that Daniel links to.

The basic principle is, have the Task object keep an explicit reference to its parent. Hold onto the Task object across screen rotations, (using onRetainNonConfigurationInstance), and then in onCreate, make sure that if the Task exists and you're coming from a screen rotation, set the Task's parent activity to the new instance. Inside the task, make sure to call all Activity methods on the explicit parent.

You can see an example of me doing this on a basic ListActivity here: http://github.com/klondike/android-campfire/blob/master/src/com/github/klondike/android/campfire/RoomList.java

One thing I'd do differently than in that example, is that I'd move as much of the Task's onPostExecute into a method on the Activity, just for code cleanliness reasons.

Klondike
A: 

Click Here for a great thread posted to the android-developers listserv with some good information on handling screen transitions or incoming calls while running an AsyncTask.

It's written by Mark Murphy from http://commonsware.com/

He includes a link to one of his projects that uses a bus system for handling background threads. https://github.com/commonsguy/cwac-bus/tree

I ended up implementing something that looks a lot like this post in my application and it is working great!

Austyn Mahoney