Monday, July 18, 2011

Why Android’s Async Task isn’t Always the Best Choice

Anyone that has done any sort of Android Development knows about the AsyncTask. Many developers live and breath by it. However, it can’t solve every problem that requires asynchronous messaging.

An AsyncTask provides a few handy functions that allow it to update the UI whenever it’s done doing work. OnProgreesUpdate, OnPreExecute, and OnPostExecute allow the AsyncTask to update the UI with whatever information it needs. These methods work great when developing an Android client, but what about a Library?

That’s where I hit a problem. When building an Android library, asynchronous methods will need to be used, and the UI will certainly need to be updated. But by using an AsyncTask, the functions to update the UI need to be defined within an AsyncTask. This is bad. This means that any AsyncTasks used within an Android Library would be updating the UI, which should really be left to the Client Developer.

Now What?

So in developing an Android library, I’m looking for AsyncTask that allows updating of the UI to be done by a different developer, not the library Developer. I can think of two different methods to do this:
  1. Create Listener Interface for the AsyncTask, and a callback handler that allows the user of the library to “listen” for updates from the AsyncTask.
  2. Create a new version of the AsyncTask with its own listener and handlers.
Because an AsyncTask has its own handlers that hook into the UI, and it has the limitation of only being allowed to be started from the UI thread (no creating an Async Task inside an Async Task), I went with the second option.
Here's a rundown of what method two needs.

Creating a Listener

The listener is what the client creates to listen to updates from your new asynchronous method. Under the hood, the listener is a simple interface that defines several methods the client should implement.
   1: public interface Listener {
   2:     public void onUpdate(parameters....); //What the client should do went an 
                                                //update is recieved from the new 
                                                //async task
   3: }

 

Creating a Callbackhelper

The callbackhelper has a handler that points to the UI thread. It is used by the new asynchronous method to update the UI thread from a different thread. The method that kicks off the asynchronous method must have access to this handler. For this example, I created a private class that has a listener and a handler. This class also has methods that allow it to update the UI.
   1: private class callBackHelper() {
   2:     Handler UIhandler;
   3:     Listener UIlisener;
   4:     
   5:     callBackHelper(Handler handler, Listener listener) {
   6:         UIHandler = handler;    
   7:         UIlistener = listener;
   8:     }
   9:     
  10:     //Tell the UI that it needs to update
  11:     void doUpdate(parameters...) {
  12:         Handler.post(new Runnablenew Runnable() {
  13:             @Override
  14:             public void run() {
  15:             listener.onUpdate(parameters ...);
  16:             }
  17:         });
  18:     }
  19: }

 

Creating the New Asynchronous Method

This can now be any type of thread you can think of. For this example, I just used a Java Thread. This method is within the library, and the client can call it.
   1: public void doAsyncTask(parameters ..., Listener listener) {
   2:     final callBackHelper callbackhelper =  
              new callBackHelper(new Handler(), listener);
   3:  
   4:     //implement a Thread here and pass the callbackhelper along. 
          //Call DoUpdate whenever 
          //the UI needs to be updated
   6: } 

That’s it! The client must create a listener and send it in as a parameter to the asynchronous method. This allows the asynchronous method to update the UI thread from a different thread with ease. This works great from a library perspective. The library writer can tell the UI it needs updating, while the UI writer can determine what to do when it needs to update.

Tuesday, July 5, 2011

Off-loading Tasks in an Android Background Thread: AsyncTask versus ServiceIntent

Recently I’ve come across a typical situation for a mobile developer. I have to update a database on a mobile device with some information from a server. While doing this work, I don’t want the UI to lock up, or worse, to see the ANR error. So I’ll need to dump off any time-intensive tasks into a separate thread and update the UI when it’s done.
This is a fairly common requirement. Nearly all types of mobile applications have some sort of background work that has to be done. None of it needs to be done on the same thread as the user interface.
Whether it’s pulling down new information from the server or loading up information into memory, all of it should be done in a background thread. But the big question seems to be which type of background thread should I use?
In Android, accessing the UI elements from a separate thread can create a ton of headaches; so simply creating a standard thread, doing your work, and updating the UI is not enough to do background work.

Background Threading in Android

Luckily, Android provides several solutions for doing some work in another thread and updating the UI. Both the AsyncTask and the IntentService classes can provide this functionality to the developer with ease. But determining which one should be used for a specific task is harder than you would think. And from my “intensive” research (10 minutes with Google), I don’t see too much differentiating between when to use one or the other.
An AsyncTask allows a simple interface to do some asynchronous work in a separate thread and update the UI.
An IntentService is a basic Android Service that takes a specific Intent, does some work regarding that Intent, and finishes it.  Also, an IntentService  can take multiple requests, which it does in a sequential fashion by handling one Intent at a time.

The Upshot

The usage between the two really can be answered with one question. Does the background work tie in with one specific activity? An example would be contacting a service to verify login details. If so, you should use an AsyncTask. Otherwise, I suggest going with an IntentService.

When to use AsyncTask

One thing about AsyncTasks is that they’re directly linked to an Activity, which can either be a bad thing or a good thing – depending on what your trying to do. This means they are also subject to the Operating System’s mercy when it comes to stopping and starting the Activity.

When to use an IntentService

If the background work that needs to be done doesn’t really tie to a specific activity, it’s better to use an IntentService. That way it isn’t tied to what the user is doing at one time. The user can close the app or move to another screen, and the background work will still finish in the expected amount of time.
However, one thing to note when using an IntentService is updating the UI from a IntentService can be a bit annoying. First, the IntentService needs to broadcast an intent that contains all of the information the application needs, and then, the application needs to set up a Broadcast Receiver to get the Intent with the new information. This requires adding a new Service in the Android manifest file.
What’s your experience with using Async Tasks and IntentServices?