In this tutorial, we will discuss how to use AsyncTask correctly in android. With AsyncTask we have a love-hate relationship. On the one hand it makes really easy to get work off the main thread but on the other hand, it makes really easy to do a bunch of really bad stuff. While asyncTask provides some easy interfaces if you’re not careful it can hurt your app’s performance and end up causing memory leaks. So here is a familiar situation. The user swipes the screen kicking off some bitmap decoding to occur and because that work is going to take a long time you need to hand it off to another thread.
You don’t want to hitch in your animations but once the bitmaps have been decoded you need to get them back to the UI thread so that you can update your views. If this happens a lot in your application then it’s not worth writing all the on-off code snippets. To make this happen the right way this is exactly why AsyncTask was created it wraps up all of this gnarliness with three simple function calls. We hope that our r
Basically, the onPreExecute function will happen on the main thread. It allows you to set up the work you’re about to do. Then the doInBackground function will execute on a worker thread actually doing the computation. And finally, onPostExecute is called on the main thread along with the results of the work that you’ve just completed. Simply overload these three functions in your own class and asyncTask will do the rest.
Now while this seems like an ideal solution you need to be cautious there are some nuances with AsyncTask that can get you into trouble. Firstly all AsyncTask that are created will share the same thread and this will execute in a serial fashion from a single message queue. So if you kick off 20 work orders and the third one takes an hour the other 17 will block and wait until it’s done. This is especially dangerous if you kick off some work that’s got a long-running while loop in it. Basically, it will just freeze that thread from doing any future work.
Now to be fair there is a way to force AsyncTask executing a thread pooled fashion. But in reality, if you’re venturing into that area you might just want to use the thread pool primitive directly instead of all that madness.
Cancellation of AsyncTask
Anyhow the second big problem might be a little bit more familiar. How do you actually cancel a block of work? I mean AsyncTask has this handy cancel function but does that really do well. Remember that threads don’t directly contain the ability to interrupt the current code being executed. If you want a threaded block of work to be able to terminate early you have to do two things. Number one add some logic to check for a flag that says the work has been canceled and number two, once the block of work is finished, let the other functions know that this packets results are invalid
This is exactly what the cancel function in asyncTask does. It will set a flag and allow the isCancelled() function to return true so your code can check that regularly. To see if it should exit early. In addition after doing background returns, a canceled AsyncTask will call onCancelled on the UI thread instead of onPostExecute. This is so you can properly update UI or destroy specific memory allocations that you might not need anymore.
Memory leak due to improper use of AsyncTask
Finally be aware that it’s really really easy to leak memory with AsyncTask. This is very commonly seen code pattern in android apps. For instance, let’s take an example of an AsyncTask declared as an inner class of some activity. This is a really big problem. Having AsyncTask declared as an inner class creates an implicit reference to the outer activity which can result in memory leak. Which means it won’t be destroyed until the AsyncTask work completes. Obviously, this is less than ideal if you’re trying to load a new activity and you still have several destroyed activities and memory since their work hasn’t been completed.
The gist here is that while AsyncTask makes it really easy to move work off the UI thread it’s far from being a silver bullet. So don’t be afraid to check out some of the other threading primitives in android. In case you need a little different use case.
For example, handler threads are great when you need a dedicated thread for callbacks to land on, a thread pool works best when you’ve got a mountain of small work objects to do and intent services are really ideal for background tasks or when you need to get work off of the UI thread.
And see that’s the whole thing when it comes to performance coding. You have to understand enough about the primitives to know how they might help you and how they might hurt you. And if it’s not working move on to a better pattern.