Deep-Dive

Intent Factories and Building

As an Android Developer, we use Intents all the time. We use them to start Activities, Broadcast Receivers, and Services.

But like many of the Android APIs, they aren’t exactly pleasant to work with. Intent can have extras, action, and data. And when we start up an activity (or other system component) we need to remember to set up the intent with all the extras, action, and data the subsequent component will expect.

The Medium app handles both of these annoyances with simple, clean solutions.

The Problem of creating and setting up intents is handled with their IntentBuilder class. This class follows the Builder pattern to make creating and setting up an intent incredibly simple and straight-forward.

IntentBuilder (or how to improve a mediocre API)

The IntentBuilder class has two static factory methods as entry points.

A nice bonus here: Notice the bounded wildcards for the class type parameter to ensure that any intents that get created are always to launch subclasses of their base service/activity class (something the default intent constructor does not enforce.)

After initializing the builder, you can do a multitude of set-up operations.

Extras handling is done with a few named methods for Strings, JsonSerializables, and Serializables.

Using this intent builder pattern wrapping the extras, you could pass in any fundamental types you use in your app. Perhaps you have some Loggable interface that outputs a String, or an XMLSerializable type that can output a string you can serialize and deserialize into some xml object.

Action’s are optional in Intent’s and so the action field in the intent builder is Optional. While the normal android intent interface expects a String as the data, there is a limited and specific amount of actions supported by the os. Here instead of an unsafe String, they concretize the valid supported actions in an Enum to make intent action setting more typesafe and readable.

URI handling is done using the default android.net.URI builder. Obviously, by abstracting this out, there is a nice api for uri handling, and again, has only these safe methods to make sure the URI is valid and well-formed.

Finally we have the build, where everything comes together and we return an Intent to start. Notice in this particular implementation, they DRY out the domain and scheme for the URI building and even do some String case management for the component.

Different applications will have some different operations in the build method, but separating the construction process out like this gives you a great deal of flexibility, validation, dry-ness, and conciseness (not to mention, a more readable, idiot-proof API for creating Intents).

IntentBuilder Consumers in the Wild

Here are a few examples in the app which hook into the IntentBuilder.

One-line, foolproof, semantically named and context-parameterized Intent creation. Yes please!

This is an overall an excellent pattern. While Activities cannot have parameterized constructors (as their creation and lifecycle is handled by the OS) having a (or multiple named) intent factories makes it clear what that activity expects.

Even better, any data-type processing, null-checking, data-wrangling, or decision-making around an intent to launch this activity can be done at this level, in one place.

And, to top it all off, creating an proper intent to launch the activity with everything it needs is only one line, instead of the usual five or six.

This is a great little pattern and one that any multi-activity application should consider implementing. Especially if they have a complicated deep-linking URI schemes, or fully-decked-out Intents.