Effective Android #1

If ever a technology was crying out for a practitioner’s guide capturing usage it’s Android; it’s really complex. Whilst I await my advance for writing such a book, here is a snippet of advice that I’ve found useful in my work.

Rule #1: Consider alternatives to explicitly starting activities with an Intent

An Intent is an object that provides runtime binding between separate components (such as two activities). The Intent represents an app’s “intent to do something.” You can use intents for a wide variety of tasks, but most often they’re used to start another activity.

The following example shows how an Intent can be used to start the activity “MyActivity”:

Intent intent = new Intent(this, MyActivity.class);

As the Android conversant amongst us know doubt are aware, I can also use the Intent to pass data to MyActivity:


final String EXTRA_MESSAGE = "uk.ac.cam.cl.MessageData";

Intent intent = new Intent(this, MyActivity.class);
intent.putExtra(EXTRA_MESSAGE, message);

So far so standard Androidy. The problem is the Intent is a extra-linguistic contract of behaviour between the client and MyActivity. This might sound bit fancy, but it basically boils down to the fact that both the client and the activity have to agree the names and contents of the data bundle sent along with the intent.

The names and contents of the bundle form a contract (or interface) between the client and the activity. As this contract can’t be statically enforced by Java it’s rather likely to blow up in your face at runtime.

As every fool knows code blowing up at runtime isn’t pleasant and is almost guaranteed to occur at the very moment and important customer is watching. Therefore, being responsible porgrammers we can try and ensure that the names of the items in the data bundle are consitent by using a constant String value as below:


public class MyActivity extends Activity {

public static final String EXTRA_MESSAGE = "uk.ac.cam.cl.MessageData";

...
}

Intent intent = new Intent(this, MyActivity.class);
intent.putExtra(MyActivity.EXTRA_MESSAGE, message);

Again very nice and totally Androidy. But – you may be asking yourself – what is the type of the data item MyActivity.EXTRA_MESSAGE? What does the contract between the client and the activity specify? Well it isn’t specified of course! It could be an int or a String or even a long[], as the putExtra method supports these and many more besides. However, if we want to avoid the embarassment of the code blowing up in our face we kind of need to know.

To prevent such problems I like to actualy use the protections offered by the a strongly typed langauge (That’s just the way I roll. I also don’t have the time for a discussion as to whether Java is strongly typed, so that’s just assumne that it is – which it is).

I can now launch MyActivity and pass the MESSAGE_DATA through a simple static method as show below:


public final class MyActivity extends Activity {

final String EXTRA_MESSAGE = "uk.ac.cam.cl.MessageData";

public void MyActivity(...) {
}

public static void launch() {
Intent intent = new Intent(this, MyActivity.class);
intent.putExtra(EXTRA_MESSAGE, message);
}

public static void launch(final String message) {
Intent intent = new Intent(this, MyActivity.class);
intent.putExtra(EXTRA_MESSAGE, message);
}

...
}

MyActivity.launch("hello")

Now I readily admit that this pattern can’t stop crazy clients from ignoring the nice interface that I’ve so helpfully provided. But I can get medieval on anyone that has deliberately workaround my mechanism.

I’m far from an Android expert so I’d be happy to hear suggestions or reasons why my approach isn’t any good.