Sunday, May 30, 2010

The limitations of AsyncTask

AsyncTask is a fine API, it's been said that it "holds your hand", and makes performing background operations painless. It pulls this off so well in fact, that I see people overusing it in situations where it's not really appropriate.

It's particularly unsuited for situations when you have a multiple tasks to perform concurrently. Imagine an Activity that needs to download about 30 small images from a remote server, and update the UI as these become available. AsyncTask uses a static internal work queue with a hard-coded limit of 10 elements. That means if you were to create an AsyncTask instance for each image, the work queue would quickly overflow and many of your tasks would get rejected. The best solution in this case is to create your own ThreadPoolExecutor instance that uses a queue that's large enough to hold all your tasks, if you need an unbounded queue, a LinkedBlockingQueue will work just fine.

Another severe limitation is that an AsyncTask can't survive your Activity being torn down and recreated on the other side.  Even if you pass it to the new instance via onRetainNonConfigurationState, the internal Handler inside the AsyncTask is still going to be stale and it's not going to behave correctly.  This is important to consider, and the Android documentation makes no mention of it all.  I've already blogged this scenario in detail, so I won't flog a dead horse here.

There are a few other minor issues, such as the fact that you can't change the background threads execution priority. It's hard-coded to a low priority, which granted, is the sensible default.  Also, exception handling is not very well supported.

So just to reiterate, AsyncTask is a nice API, but you should understand it's limitations and apply it appropriately.  If you're serious about writing mobile apps, then you're going to need a few more tools in the toolbox to get the job done.

Saturday, May 22, 2010

Android 2.2 Highlights, A developer's perspective

Android 2.2 is the most significant upgrade to the Android OS that I can remember. Chock full of new goodies for both users and developers.

I thought I'd just do a quickie post to highlight the features for developers I'm most interested in.

1) Android Cloud to Device Messaging - this is one feature that's been sorely lacking from the Android platform and it's a welcomed addition. The demo at Google IO demonstrated how you can push a message to a device in real time, and have it fire off an Intent which can kick off any number of interesting and yet to be dreamed of services. This also opens up a new way for devices to communicate with each other in real time over the internet, I expect interesting things to come of this.

2) Android Application Error Reports - logging exceptions remotely that occur on a users device is a very useful thing and every mobile company I've worked at has done this in some form or another. The typically way to do it is to override the default exception handler and replace it with something that will log the exception. I myself just started building a new  GAE project for this a few weeks ago http://github.com/jasonhudgins/Remote-Incident-Logger. The initial usefulness of this will be somewhat limited, due to the fact that many devices are going to be running older versions of android for the foreseeable future.

3) Stagefright media framework - I don't know much about Stagefright, I'll admit that right off the bat, what I do know is that I'm dreadfully tired with the limitations of the current MediaPlayer framework, and I'm really hopeful this can serve as an improvement / replacement for the API's we've been using up til now.

And lastly, I'd also like to mention the new support for Android Library Projects that are available in the newest SDK tools (SDK Tools r6). We will finally be able to share common resources between multiple projects, and since it's just build time magic, these new library projects are going to be backwards compatible with older platform versions.

Wrapping up, I'm really excited about android 2.2.  Google has really raised the bar with this release, and it's going to be interesting to see how other mobile technologies evolve in response to this.

Wednesday, March 31, 2010

A Simple ProgressBar Tutorial

I came across another ProgressBar tutorial a few days back posted on helloandroid.com, and while it's certainly good enough to get someone started, it doesn't really go into any detail about how your non-ui thread should work, and how it should gracefully handle Activity restarts and what not. It uses a message handler to send notifications to the ui thread, but what if the Activity is paused and the message handler becomes stale?

So I'm taking this as a good opportunity to follow up on my previous Rebel Without A Context post.

The code is fairly short, so I won't go into a line-by-line explanation of it, but the general idea is that you have your own Thread implementation that maintains state, and you pass it from the old activity to the new activity via onRetainNonConfigurationInstance(). Also rather than updating the UI directly by sending a message from the background thread, the UI thread actively polls the background thread every 50 milliseconds with a handler loop, which updates the progress bar as necessary.

With this kind of approach, you can for example, flip orientations back and forth gracefully with no stale handlers or leaky window exceptions.

Saturday, March 20, 2010

HTTP Connections revisited

In a previous post entitled, HTTP connection reuse in android, I tossed out a code snippet for an HttpClientFactory that would spit out a DefaulHttpClient implementation suitably configured for re-using already open HTTP connections to serve multiple requests across multiple threads.

My hasty implementation from that post leaves a few things to be desired. Primarily, it's a singleton implementation which can lead to some problems. Since it's effectively a global resource, doing things like modifying the time out value, or forcibly closing the connection manager (as one commenter pointed out), could lead to the HttpClient to be in an invalid or undesired state when reused at a different time or a different part of your application.

So here's a simplified version without the singleton garbage:


The ideal place to use something like this is when you want to download multiple items from a single remote source, for example, if I needed to download a bunch of thumbnails to be displayed in a ListView, I could have a thread pool downloading images concurrently and all sharing this one HttpClient instance, reusing HTTP connections as they became available (all managed inside the HttpClient)

Friday, February 5, 2010

Rebel Without A Context

The scenario is common enough. You want to implement some task in a background worker thread, like fetching data from an HTTP server or whatnot, and then at a future point the UI needs to be updated, based on whatever has or is happening in the worker thread.

So here's your naive Thread/Runnable implementation :

And there you have it. That's the most succinct implementation of the anti-pattern many people use. And certainly I must concede my own guilt of having used it.

The problem is that your background thread, in order to update the UI, is now tightly coupled to the Activity/Context that created it. So when/if an event occurs (such as an orientation change) that causes your Activity to be restarted, your background thread will continue to happily chug along and then try to update the UI even though it's still referencing the old Activity/Context. Your app is then likely to experience leaked window exceptions and other types of nastiness.

I've seen this problem attacked in different ways, generally trying to enable the background thread to update the UI on the new Context. The droidfu library has an AsyncTask implementation called BetterAsyncTask that does exactly that.

But this isn't a perfect solution in my opinion. Imagine that an important event occurs in the background thread, one that is serious enough that the user absolutely should be informed if they continue to use the app. What if it happens in the middle of an orientation change, after the old Activity has been destroyed, yet before the new Activity is fully initialized? A quick glance at BetterAsyncTask's source suggests that the message would never get delivered:


Now before I get into what I don't like about this, I just want to say that I applaud the creators of droidfu for releasing an open source library, and I've never used it myself, but that's my five second synopsis of it's implementation. It probably works fine for a lot of people, but I demand something more robust.

The way I see it, this just doesn't escape the anti-pattern. The core point that I'm trying to make here is this:

It's your Activity's responsibility to update the UI, not the responsibility of the worker thread.

Let me say that again, your background thread should not try to update the UI. What it can and should do is track it's own internal state, and allow itself to be queried by the active Activity instance. The simplest way to accomplish this is to use onRetainNonInstanceConfiguration to pass your Thread/AsyncTask implementation to the newly created Activity. The Activity can then query the state of your thread and deal with any impending UI events that it needs to process.

A simple, but effective way to accomplish this is with a polling Handler loop running in the UI thread. Something like this will work fine as long as you remember to shutdown the loop as your activity exits.


If this isn't realtime enough for you, then another approach would be to have your Activity register listeners with your thread, much like binding to a service and registering a remote callback. In fact, that's exactly how you should think about your background thread, as a lightweight service, that is decoupled from any direct UI interaction.

And just a quick warning as I wrap up, If you go the listener route, you still must be aware that events can occur when your Activity is being restarted, and before the new activity can register another listener instance.

I hope this article helps a few of you out there, or at the very least, shows you a different approach to a common problem.

Monday, February 1, 2010

Android Sweater

We didn't want to be left out of the Android arts and crafts mania, you know, the
various android pillows and dolls, so grandma hand knitted this sweater for Maxim.

Saturday, January 2, 2010

droidworks library announcement

One of the best things a developer can do to increase productivity is to build yourself up a nice code library. I've decided to open source mine. As a tradition, I've typically called such libraries "kitchensink", because of the hodge-podge of code they typically contain.

In the past whenever I created a library like this I have always used maven. I grew quite fond of maven (and remain so) during my stint as an enterprise java developer. However since this library is primarily for android development, it's just going to be bundled as a simple eclipse project.

I just started this library so there's not a whole lot of useful stuff in it, but the primary things of interest are a RSS 2.0 parser and a gdata parser for youtube video feeds. Neither of these is 100% complete. It's so new I haven't even bothered with versioning yet, and I'm not sure if I ever will.

I'm hosting this project on github here :

http://github.com/jasonhudgins/droidworks-android-kitchensink