93

Quoting the documentation for AsyncTask found here, it says:

AsyncTasks should ideally be used for short operations (a few seconds at the most.) 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.

Now my question arises: why? The doInBackground() function runs off the UI thread so what harm is there by having a long running operation here?

4
  • 2
    The problem I faced while deploying an app(that uses asyncTask) to an actual device was that the long-running doInBackground function freezes the screen if a progress bar is not used.
    – venkatKA
    Commented Oct 9, 2012 at 10:10
  • 2
    Because an AsyncTask is tied to the Activity it is launched in. So if the Activity is killed, your AsyncTask instance can get killed as well. Commented Feb 7, 2014 at 16:44
  • What if I create the AsyncTask within a Service? Wouldn't that solve the problem?
    – eddy
    Commented Sep 4, 2014 at 12:06
  • 1
    Use IntentService, Perfect solution to run long operation in background. Commented Feb 1, 2017 at 3:44

4 Answers 4

121

It is a very good question, it takes time as an Android Programmer to fully understand the issue. Indeed AsyncTask have two main issues that are related :

  • They are poorly tied to the activity life cycle
  • They create memory leaks very easily.

Inside the RoboSpice Motivations app (available on Google Play) we answer that question in detail. It will give an in-depth view of AsyncTasks, Loaders, their features and drawbacks and also introduce you to an alternative solution for network requests : RoboSpice. Network requests are a common requirement in Android and are by nature long running operations . Here is an excerpt from the app :

The AsyncTask and Activity life cycle

AsyncTasks don't follow Activity instances' life cycle. If you start an AsyncTask inside an Activity and you rotate the device, the Activity will be destroyed and a new instance will be created. But the AsyncTask will not die. It will go on living until it completes.

And when it completes, the AsyncTask won't update the UI of the new Activity. Indeed it updates the former instance of the activity that is not displayed anymore. This can lead to an Exception of the type java.lang.IllegalArgumentException: View not attached to window manager if you use, for instance, findViewById to retrieve a view inside the Activity.

Memory leak issue

It is very convenient to create AsyncTasks as inner classes of your Activities. As the AsyncTask will need to manipulate the views of the Activity when the task is complete or in progress, using an inner class of the Activity seems convenient : inner classes can access directly any field of the outer class.

Nevertheless, it means the inner class will hold an invisible reference on its outer class instance : the Activity.

On the long run, this produces a memory leak : if the AsyncTask lasts for long, it keeps the activity "alive" whereas Android would like to get rid of it as it can no longer be displayed. The activity can't be garbage collected and that's a central mechanism for Android to preserve resources on the device.


It is really a very very bad idea to use AsyncTasks for long running operations. Nevertheless, they are fine for short living ones such as updating a View after 1 or 2 seconds.

I encourage you to download the RoboSpice Motivations app, it really explains this in-depth and provides samples and demonstrations of the different ways to do some background operations.

12
  • @Snicolas Hi. I have an app where it scans data from an NFC tag and sends to server. It works fine in good signal areas but where no signal the AsyncTask that makes the webcall keeps running. eg the progress dialog box runs for minutes and then when it does disappear the screen turns black and unresponsive. My AsyncTask is an inner class. I'm writing a Handler to cancel the task after X secs. The app seems to send old data to the server hours after the scan. Could this be due to AsyncTask not finishing and then maybe completing hours after? I would appreciate any insight. thanks
    – turtleboy
    Commented Jul 18, 2013 at 21:26
  • Trace to see what happens. But yes, that's quite possible ! If you desin well your asynctask, you can cancel it rather properly, that would be a good starting point if you don't want to migrate to RS or a service...
    – Snicolas
    Commented Jul 19, 2013 at 5:56
  • @Snicolas Thanks for the reply. I made a post on SO yesterday outlining my problem and showing the handler code i've written to try stop the AsyncTask after 8 seconds. Would you mind having a look at, if you get time? Will calling AsyncTask.cancel(true) from a Handler cancel the task properly? I know i should check periodically the value of iscancelled() in my doInBackgroud, but i don't think applies to my circumstances as i'm just making a one line webcall HttpPost and not publishing updates on the UI.Are there alteratives to AsyncTask eg is it possible to make a HttPost from an IntentService
    – turtleboy
    Commented Jul 19, 2013 at 9:12
  • here's the link stackoverflow.com/questions/17725767/…
    – turtleboy
    Commented Jul 19, 2013 at 9:12
  • You should have a try at RoboSpice (on github). ;)
    – Snicolas
    Commented Jul 19, 2013 at 9:31
38

why ?

Because AsyncTask, by default, uses a thread pool that you did not create. Never tie up resources from a pool that you did not create, as you do not know what that pool's requirements are. And never tie up resources from a pool that you did not create if the documentation for that pool tells you not to, as is the case here.

In particular, starting with Android 3.2, the thread pool used by AsyncTask by default (for apps with android:targetSdkVersion set to 13 or higher) has only one thread in it -- if you tie up this thread indefinitely, none of your other tasks will run.

6
  • Thanks for this explanation.. I could not find anything truly faulty about the use of AsyncTasks for long-running operations (although I usually delegate those to Services myself), but your argument on tie-ing up that ThreadPool (for which you can indeed make no assumptions about its size) seems spot-on. As a supplement to Anup's post about using a service: That service should itself also run the task on a background thread, and not block its own main thread. An option could be an IntentService, or, for more complex concurrency requirements, apply your own multithreading strategy.
    – baske
    Commented Oct 9, 2012 at 11:33
  • Is it the same even if I start the AsyncTask inside a Service?? I mean, would the long running operation still be a problem?
    – eddy
    Commented Sep 4, 2014 at 12:04
  • 1
    @eddy: Yes, as that does not change the nature of the thread pool. For a Service, just use a Thread or a ThreadPoolExecutor. Commented Sep 4, 2014 at 12:08
  • Thank you @CommonsWare just the last question, does TimerTasks share the same disadvantages of AsyncTasks? or Is it a whole different thing?
    – eddy
    Commented Sep 4, 2014 at 12:13
  • 1
    @eddy: TimerTask is from standard Java, not Android. TimerTask has largely been abandoned in favor of ScheduledExecutorService (which, despite its name, is as part of standard Java). Neither are tied to Android, and so you still need a service if you expect those things to run in the background. And, you really should consider AlarmManager, from Android, so you do not need a service hanging around just watching the clock tick. Commented Sep 4, 2014 at 12:17
4

Aysnc task are specialized threads that are still meant to be used with your apps GUI but whilst keeping resource-heavy tasks of the UI thread. So when stuff like updating lists, changing your views etc require you to do some fetch operations or update operations, you should use async tasks so that you can keep these operations off the UI thread but note that these operations are still connected to the UI somehow.

For longer-running tasks, which don't require UI updation, you can use services instead because they can live even without a UI.

So for short tasks, use async tasks because they can get killed by the OS after your spawning activity dies (usually will not die mid-operation but will complete its task). And for long and repetitive tasks, use services instead.

for more info, See threads:

AsyncTask for longer than a few seconds?

and

AsyncTask won't stop even when the activity has destroyed

1

The problem with AsyncTask is that if it is defined as non-static inner class of the activity, it will have a reference to activity. In the scenario where activity the container of async task finishes, but the background work in AsyncTask continues, the activity object will not be garbage collected as there is a reference to it, this causes the memory leak.

The solution to fix this is define async task as static inner class of activity and use weak reference to context.

But still, it is a good idea to use it for simple and quick background tasks. To develop app with clean code, it is better to use RxJava to run complex background tasks and updating UI with results from it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.