Thursday, March 31, 2011

Android Thread Constructs(Part 4): Comparisons

In this series of posts we have seen the following thread constructs:
1. Basic threads and communication between them [see article]
2. Understanding the Main thread or the UI thread [see article]
3. IntentService [see article]
4. AsyncTask [see article]

NOTE:  These are Android specific constructs. Android also includes the java.util.concurrent package which can be leveraged for concurrent tasks. That is out of the scope of my discussion.]

So, when to use what ? What is the exact purpose of each ? What are the drawbacks of using one over the other ? Which one is easier to program ?

I came across all these questions when trying to understand each of these. In due course of time, I have come up with some guidelines which I discuss in this post.

NOTE: Any of the recommendations made in this post and the table below are not comprehensive and final. There may be better and alternate ways of doing things. I would love to know any different views and get an insight into a different thought process. The views expressed in this post are my personal views.

Service
Before proceeding further, let me touch on the Service class. Traditionally speaking, the notion of service reminds us of task running in the background while we can work and interact with the UI. This causes confusion for newbies. Because in Android, even if the Service runs in the background, it runs on the Main Thread of the application. So, if at the same time if you have an activity displayed, the running service will take the main thread and the activity will seem slow. It is important to note that a Service is just a way of telling Android that something needs to run without a user interface in the background while the user may not interacting with your application. So, if you expect the user to be interacting with the application while the service is running and you have a long task to perform in a service, you need to create a worker thread in the Service to carry out the task.
So, even if Service is not a threading construct, its a way of executing a task at hand. Hence I have included it in the comparison.

The table below tries to summarize various aspects of four task execution mechanisms : Service, Thread, IntentService, AsyncTask.

Most of the points in the table are self-explanatory. However, some points that need an explanation are numbered and explained  below the table. Also, this table is just to summarize about the concepts discussed in the previous posts. So, if anything is still unclear, I recommend to go through each individual posts in this series.



ServiceThreadIntentServiceAsyncTask
When to use ?Task with no UI, but shouldn't be too long. Use threads within service for long tasks.- Long task in general.

- For tasks in parallel use Multiple threads (traditional mechanisms)
- Long task usually with no communication to main thread.
(Update)- If communication is required, can use main thread handler or broadcast intents[3]

- When callbacks are needed (Intent triggered tasks). 
- Relatively long task (UI thread blocking) with a need to communicate with main thread.[3]

- For tasks in parallel use multiple instances OR Executor [1]
TriggerCall to method
onStartService()
Thread start() methodIntentCall to method execute()
Triggered From (thread)Any threadAny ThreadMain Thread (Intent is received on main thread and then worker thread is spawed)Main Thread
Runs On (thread)Main ThreadIts own threadSeparate worker threadWorker thread. However, Main thread methods may be invoked in between to publish progress.
Limitations /
Drawbacks
May block main thread- Manual thread management

- Code may become difficult to read
- Cannot run tasks in parallel.

- Multiple intents are queued on the same worker thread.
- one instance can only be executed once (hence cannot run in a loop) [2]

- Must be created and executed from the Main thread

[1] API Level 11 (Android 3.0) introduces the executeOnExecutor() method, that runs multiple tasks on a thread pool managed by AsyncTask. Below API Level 11, we need to create multiple instances of AsyncTask and call execute() on them in order to start parallel execution of multiple tasks.

[2] Once you create an object of an AsyncTask and call execute, you cannot call execute on that object again. Hence, trying to run an AsyncTask inside a loop will require you to each time create a new object in the loop before calling the execute on it.

[3] Recently I was brought to notice that AsyncTask is not recommended for long running tasks. While this is technically possible, I agree with the commenter. The idea here is any task which would potentially block the UI thread - I referred to this as a long task. May be I should have been clear. Thank you for pointing it out.


To be very precise, you cannot do something like :
        TestAsyncTask myATask = new TestAsyncTask();
        for (int i = 0; i < count; i++) {
            myATask.execute("one", "two", "three", "four");
        }

But you can do :
        for (int i = 0; i < count; i++) {
            TestAsyncTask myATask = new TestAsyncTask();
            myATask.execute("one", "two", "three", "four");
        }

[3] Thanks to comment posted by Mark Murphy (@commonsguy) : "there's nothing stopping an IntentService from communicating back to activities. A broadcast Intent is good for that, particularly with setPackage() to keep it constrained to your app (available on Android 2.1, IIRC). An ordered broadcast can be particularly useful, as you can rig it up such that if none of your activities are on-screen, that some manifest-registered BroadcastReceiver picks up the broadcast and raises a Notification."

Conclusion:
With a pretty understanding of the AsyncTask and the IntentService classes provided by Android, it would be a good idea to leverage these for most of the tasks as against trying to manage threads manually or implement your class as a Service unless there is really a need to do so.

Tricky Things:
There are some tricky scenarios that need some special handling. After all, we are dealing with a mobile environment and things are pretty unpredictable. For instance, the user opens your activity in which you start an AsyncTask, but before completion of the task, the user decides to exit the application (say by pressing the back button). Or your activity may be terminated (read kicked off) due to say an incoming call, when you are running a long task in the background. In such cases, where your application is not shutdown, but any foreground tasks have been closed or changed, all the background tasks need to know of this and try to exit gracefully.

Friday, March 18, 2011

Android thread constructs (Part 3) : AsyncTask

After examining thread communication, UI thread and then IntentService, I would like to talk about another threading construct called AsyncTask.

Similar to IntentService, AsyncTask allows us to run relatively long running tasks in the background. However, unlike IntentService the implementation is not straight forward. One of the reason people might think is that it involves generics ! There is no need to be afraid about those really. We just need to know 2 important things. One is the type of data that will be moving around and secondly these types cannot be primitive types like int, float, boolean etc... Before going further into the implementation, let me try to explain at a conceptual level.

NOTE: Recently I was brought to notice that AsyncTask is not recommended for long running tasks. While this is technically possible, I agree with the commenter. The idea here is any task which would potentially block the UI thread - I referred to this as a long task. May be I should have been clear. Thank you for pointing it out.

Concept:

You have a long task to do. You extend the AsycTask class and somewhere in there, specify your task. Then, from the main thread, create an instance of your extended class and call the execute() method. This should somehow result in a background thread executing your task. Pretty simple !

Now, there are 3 kinds of data that you will be dealing with:
1) Params : The parameters you pass on to the background task
2) Progress : The data units which the background task will be passing to you (UI thread) reporting its progress.
3) Result : The data that will be returned by the background task (to the UI thread) on completion.

Clearly there seems to be a communication going on between the UI thread and the worker thread. Hence, I like to visualize the AsyncTask as follows:


All the methods mentioned in the diagram will be a part of the extended AsyncTask class but however will run on different threads as indicated.

1) You have an instance of the AsyncTask and will call the execute() method. This method runs on the UI thread and serves as a trigger to the platform to spawn a worker thread.

2) Before handling the control to the worker thread, the platform will execute the onPreExecute() method on the main thread. We can perform any necessary task setup.

3) After this method finishes, the platform executes the doInBackground() method on the worker thread.

4,5) Now, whenever the worker thread calls the publishProgress() method, the platform calls the onProgressUpdate() method on the main thread with the parameters passed to the publishProgress() method.

6,7) Finally when the long running task is over i.e. the doInBackground() method returns, the return value is passed to the onPostExecute() method.

And, for all this to happen our AsyncTask class needs to know the datatypes for the 3 kinds of data discussed above.

It is important to note that just like IntentService, AsycTask also spawns a SINGLE worker thread and hence only one task can be run in background. Furthermore, once an instance of our AsyncTask is created, you can call the execute() method on it only ONCE. An exception will be thrown if you try to call execute() on the same instance of AsyncTask more than once. Hence, with AsyncTask if you want to run multiple tasks in background, create multiple instances and call execute on them.


Note: API level 11 (Honeycomb) adds the executeOnExecutor() method which enables to run multiple tasks on a pool of threads managed by AsyncTask class. I have not studied and tried this. I will update the post (or write a new one) once I try this out.


Implementation details:

Extend the AsyncTask class and pass to it the datatypes for Params, Progress and Result

class TestAsyncTask extends AsyncTask<String, Integer, Integer> {
}

So, here, we are telling that our worker thread will accept String parameters as input, the worker thread may publish the progress to the main thread as an Integer value and finally the return value of the doInBackground method will be an Integer. Note that the Integer class is used instead of primitive data type int.

Now, It may happen that, you have a worker thread that doesn't need any input, doesn't wish to convey any progress or any result. In that case, the AsyncTask definition will look like:

class TestAsyncTask extends AsyncTask<Void, Void, Void>{
}

Okay. Sticking with the first example, lets add in the doInBackground, onProgressUpdate and onPostExecute methods.


class TestAsyncTask extends AsyncTask<String, Integer, Integer> {

    protected Integer doInBackground(String... strings) {
        // Long running task - say processing of each passed string
        for (int i = 0; i < strings.length; i++){
               // Do processing of strings[i]
              publishProgress(i); // publish that ith string is processed
        }
        return 0;
    }

    protected void onProgressUpdate(Integer... item){
        Log.d("TestP", item[0] + " item has been processed");
    }

    protected void onPostExecute(Integer result){
        Log.d("TestP", "AsyncTask returned : " + result);
    }
}


From the main thread (say from your Activity or service), create an instance of the AsyncTask.

        TestAsyncTask myATask = new TestAsyncTask();
        myATask.execute("one", "two", "three", "four");

As mentioned before, if you want to run multiple AsyncTasks in parallel, just create another instance and call execute on it.
        TestAsyncTask myATask2 = new TestAsyncTask();
        myATask2.execute("five", "six", "seven", "eight");

There are 4 threading rules we need to follow for AsyncTask to work properly. These are mentioned in the AsyncTask documentation,  but I'll mention those again so that everything is available at one place.

1. The task instance needs to be created on the main thread.
2. The execute() method needs to be called on the main thread.
3. Do not  explicitly call any of the preExecute(), postExecute(), doInBackground() and onProgressUpdate() methods.
4. The task can be executed only once on one instance.

Thats all you need to know to execute AsyncTask.
I'm pretty much excited about my next post. I'm planning to do a comparison of various background mechanisms that we have seen till now as well as try to come up with some guidelines. I'm still working on it, hope to post them soon. Stay tuned !

Thursday, March 17, 2011

Android Thread Constructs(Part 2): Intent Service

Continuing from Part 1 about the UI thread, today, I would like to discuss the IntentService class.

Concept:


In simple terms, IntentService provides a mechanism to run a long task in the background. We need not worry of any thread creation and management. It is all done behind the scene. We just extend our class from the IntentService class, and implement our long task in the overridden onHandleIntent() method.

On the specified trigger (which is an Intent), the platform will spawn a worker thread for our extended class and then call the onHandleIntent method on this thread. I like to visualize this as follows:

So, all the long running code can be executed in the onHandleIntent() method. We can be sure that this will not block the main (UI) thread.

It is worth noting here that if there are multiple intents that are received, they all will NOT execute in parallel. The IntentService class spawn a SINGLE worker thread. Hence all the consecutive intents will go into the message queue for the worker thread and will execute sequentially.

So, the obvious question is : What if I want to execute multiple tasks in parallel ?

I will defer to answer this till the end of this article series. We will first go through AsyncTask in the next article and then the concluding post I will try to consider various use cases, limitations and comparisons.

Implementation details:
Now for some implementation details. Extend your class (say MyIntentService) as follows:

class MyIntentService extends IntentService {
    public MyIntentService() {
        super ("com.foo.MyIntentService");
    }
    protected void onHandleIntent(Intent intent) {
        // call to any long running task !
    }
}

Thats it. You are all set ! Now, you can trigger this by calling the startService(Intent) method. We need not worry about stopping the service. Once the long running task is done and if there are no intents lined up in the message queue, the platform will automatically stop the IntentService.

I have stated again and again, IntentService is very useful when you need to perform a long task in the background. The interesting part here is that the trigger for starting the task is an Intent ! Now that opens a lot of opportunities. Don't get it ?  Here is hint : Your application need not be running at the time you want to start a background task ! All you need to do is have a PendingIntent for your IntentService. Now you can register this PendingIntent with many of the available callbacks in the Android APIs. So, now, even if your application is not running, and the PendingIntent is fired ! Wolaa - your background task is started  :)

Coming up next is AsyncTask.

Friday, March 11, 2011

Android Thread Constructs(Part 1): The UI Thread

Earlier, I talked on passing data between threads. I would like to continue the same "thread" of discussion and in the next few posts of this multipart article, explore and try to explain about various ways of performing tasks.

A pictorial and diagrammatic representation makes me understand concepts well. Every time I learn something new, I try to make a diagram in my mind. This helps me understand better. So, I'll be providing my own diagrams along the way.

Note : The diagrams I use are to help myself understand the concept and may not be an exact representation of the concept. You may still need to read the related documentation.

Enough said, lets get into the Thread !

The UI Thread:

So, in an Android application, each application is sandboxed and runs in its own process. Unlike traditional languages, the Android application may not have a single entry point. So, the application can be entered through from any of the application components (Activities, Services, Broadcast receivers) described in the Application Fundamentals on the developer blog.

All these application components run on a single Main thread called as the UI thread. I like to imagine this concept as in figure below:

So, as you see all the components will run on the MainThread or the UI thread. All the lifecycle methods (of Activity, Service, Receivers starting with on*) will run on the UI thread.

One of the main task of the UI thread is to manipulate the user interface. Hence, if you have long tasks to perform, you should not be doing those in the main thread. (I'm sure, you must have read this several times). The reason is that if you perform any long or blocking task - the UI thread will be blocked - hence blocking or delaying the UI updates and will lead the user to think that the system is running slow. The Android platform doesn't want this blame on itself, so when it detects that some long task is running on the UI thread for some application, it will declare that the application is "foobar-ed" and throw out the nasty ANR (Application Not Responding) dialog - pissing off the user and provoking him/her to uninstall, and underrate your application ! Deadly and Evil  :O

So, in order to do longer tasks, from any of the application components, you should create threads. However, its worth noting that you should not manipulate the UI from any worker thread. i.e for example if you run a long task on a thread on a button click as follows:


public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
      Bitmap b = loadImageFromNetwork();
      mImageView.setImageBitmap(b);
    }
  }).start();
}
Code source : http://developer.android.com/resources/articles/painless-threading.html

Here, the worker thread is trying to update the UI. As the documentation states, this may lead to hard to find and funny (not for you) problems. So, updating the UI is the job of the main thread. The following figure helps me remember that :)


Now, it is evident and advisable that we do long and/or blocking tasks on worker threads and if any results are produced, convey them to the main thread. In my previous article, I talked about passing data around threads. This involves implementing Handlers, making appropriate Looper calls, obtaining the Message Object and passing it around, getting data from it blah blah blah... (Go read the article if you havent')

Android provides certain constructs that offload from us the tasks for creation and administration of threads and let us focus on what we need to do. IntentService, AsyncTask, HandlerThread are among those.

I'm going to discuss IntentService and AsyncTask (with my diagrammatic representations) in the next articles and then try to come up with rough guidelines regarding when to use each of the constructs.

Stay tuned.