简体   繁体   中英

Android: How to retain AsyncTask instance when Activity gets destroyed?

In my app, I have a class that inherits from AsyncTask and which downloads huge amounts of data from the server. I am using a ProgressBar to indicate the progress of the download.

When the user hits the HOME key, the Activity to which this AsyncTask is attached, is destroyed but, download goes on.

How can I reattach this AsyncTask and show the progress to user? I tried using onRetainNonConfigurationInstance but Android 4.0 doesn't seem to invoke this method. My application does not use Fragments API.

What I did in this situation was as follows:

  1. I created an IntentService to handle communication with the server. This has some of the benefits of AsyncTask (eg, worker thread), but also some benefits of a Service (available any time, from anywhere).
  2. The IntentService can be invoked either by a user action in my main Activity, or via an inexact repeating alarm .
  3. The data is stored in an SQLite database , fronted by a ContentProvider . I dodge the issue of when/how to create my database and tables by using an SQLiteOpenHelper and calling getWritableDatabase() from the safety of my background IntentService.
  4. When the task is done, it posts a Notification if my main Activity is not active.

One nice thing about this arrangement is, no progress bar is necessary. In fact, no UI is necessary. The user keeps using the application while the service is running, and the UI automatically refreshes itself as new data comes into the ContentProvider. Another nice aspect of it is it's less code to write than an AsyncTask. It automatically picks up where it last left off by reading the server-side metadata of the last entry from the database and asking the user to start after that point. Since it's not tied to any Activity instance, it doesn't care about onPostExecute() or configuration changes or any of that. And you don't have to worry about single-shot execution like AsyncTask.

If there is a need to download huge amount of data in background I would use service rather then AsyncTask. There is a good presentation from Google IO about using services.

Quote from AsyncTask documentation:

If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and FutureTask.

and

The task can be executed only once (an exception will be thrown if a second execution is attempted.)

As I understand, you cannot proceed with your last AsyncTask. Still, you can load your data partially and save amount of data read and then start new AsyncTask which will start from last saved point. From my point of view this is not the best idea to pause loading when activity goes to background and it is better to use service to finish what was started.

Have you considered using a service to attach your AsyncTask to? Seeing as a permanently running service would probably be the best solution for your task at hand. All you'd have to do then will be to check if the service is running and if your download is running (easily done using static boolean variables) then you just create a progress dialog using some state saving variable in your service (maybe a percentage of the total file size downloaded etc.) in the onCreate method of your main activity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM