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

Monday, November 30, 2009

Unit Testing Your Brain

This post has been stewing around in my brain for awhile. I've wanted to write about memorization and it's role in being a productive programmer. For many a developer, the web acts as a useful crutch (and I'm as guilty as anyone).



As an example, I noticed that every time I wanted to do some type of regular expression operation in java, I almost always resorted to googling for a java regex tutorial to relearn how to do it. It's really quite an easy api to use, but it was one of those things that just wouldn't stick in my head for more than a few days at most.

There is a class of general programming tasks that I don't do frequently enough to have them automatically committed to memory, but at the same time I do use them frequently enough that I found myself wasting time relearning things over and over again. After relearning the same thing 3 or more times, I started asking myself if there wasn't some tool I could use to improve the situation.

I had a discussion about this with Curtis Dunham, who introduced me to a really neat, but hard to pronounce application called Mnemosyne.

Mnemosyne is a GUI app, written in Python and runs on all the popular platforms. It acts as a system of flash cards. You create a "deck" of cards with questions and answers, and invest a few minutes of your time each day answering them. As you answer each question, you rate your memorization on scale of 1-5. Mnemosyne then uses this information to create a dynamic schedule of questions for you based on what you're having the most trouble memorizing.

The way I use it is analogous to a common unit testing technique, where whenever you have a program fault, you create a unit test for that specific fault, and then implement a fix. I apply this same technique with Mnemosyne. If I am faced with a programming task that I can't remember how to perform, but I at least know that it was something I had already learned once before (a memory fault), into the deck it goes. The deck acts as a suite of unit tests for my brain this way.

Now if I want to do a pattern match in Java, I no longer spend time looking for examples in old source code or hitting up search engines. Mnemosyne is a free app, that with a small investment, can pay large dividends.

Saturday, November 21, 2009

Personal Update

I've been too busy lately to keep the blog updated, but life will be getting back to normal shortly. My family has just finished relocating from Dallas, TX to Dayton, OH.

I've been working fulltime at TuneWiki Inc since August, developing some very exciting products. I'm now working out of their central development hub with fellow Android hacker Zach Hobbs.

The team here is great, I expect to be both contributing and learning a lot. I've got a backlog of blog articles I need to hammer out.

Saturday, August 22, 2009

Building location aware applications

There are 3 basic ways your typical smart phone can acquire a location fix, these being :

  • Cell Tower Triangulation
  • GPS
  • WiFi Scanning
Cell Tower Triangulation is the least accurate of the 3 methods. The accuracy varies by about 2-5 km in my experience. But it does have a couple of advantages, it works fine indoors and is quick to compute.

GPS is the one most people are familiar with, and it offers the highest accuracy. It can pinpoint your location down to a few meters. However, it typically doesn't work well indoors (if at all), and acquiring an accurate fix can take up to several minutes. The longer the GPS is running the more accurate a fix can be obtained.

WiFi Scanning is relatively a new idea and is pretty interesting one. Imagine sending out a fleet of vehicles down every major thoroughfare, each armed with sensitive WiFi detection equipment. You then record the location of every WAP they detect along with the relative signal strength. Once you've collected enough data, any WiFi enabled device in the area can look around at the nearby WAPs (it doesn't actually have to connect to them), and use the data to deduce a reasonable approximation of the device's current position. It's fast to compute, it works indoors, and has decent accuracy (I typically get about 200m). Another interesting aspect of this type of system is that it can correct/improve itself. If you have a WiFi fix and a GPS fix at the same time, that information can be recorded to improve accuracy in the future.

You want to avoid writing any type of application that requires continuous/real-time location data for extended periods of time. The bottom line is, if you're crunching GPS data, the CPU is not sleeping, and you're running down the battery. The best you can do is to wake the device up at repeated intervals, get a fix, and then let it go back to sleep. This is a realistic technique and it works, but is not without limitations. An application designed to alert you when a friend is "nearby", would always have the chance of not polling for a fix was while your friend was within range. So you have to find a balance between the polling frequency, and the granularity that your app requires.

Also never underestimate the finicky nature of users regarding battery life. If they feel their device's battery is suddenly under-performing, they will look for an application to blame. If they see a flashing GPS icon, it's usually the first thing that raises an eyebrow.

Wednesday, August 19, 2009

blog relocation

This blog has been relocated to http://foo.jasonhudgins.com/, if you try and hit the old blog page you'll be redirected here. I'm currently swamped with work and falling behind on my blogging, but I've got a couple of new posts floating around in my head.