Launching android activities in a better way with Kotlin

Single responsibility + Kotlin!

Launching an activity with intent arguments is not a developer friendly experience. The major pain points are:

  • Argument serialization: intent.putExtra(key, value)
  • Argument deserialization: intent.getStringExtra(key)
  • Type safety, maintainability, and testing

What if there was a better way? Like many issues with the Android framework, we can fix this with a combination of single responsibility and dependency injection. Given the following scenario, let’s create an ideal API to illustrate.

Scenario

Build an API to launch a MediumProfileActivity that displays the following information:

Medium author bio: black text on left and red circle with man in suit staring off in distance on right

Three pieces of information will be needed to render the user interface above:

black box with purple, orange, and light blue lines of code

Creating the API

Now, let’s imagine an ideal, developer-friendly API to serialize our arguments and launch a MediumProfileActivity. It may look something like this:

black box with blue, green, dark grey, orange, and light grey lines of code

Serializing activity arguments and launching them

Inside a MediumProfileActivity, we will need to deserialize our arguments to access them later.

black box with pink, purple, orange, grey, and yellow lines of code

deserializing arguments from intent, and accessing them within our Activity

Notice no messy intent.putExtra(key, value) or intent.getStringExtra(key) code pollution. Kotlin’s lazy delegate makes this even cleaner.

We’ll use an ActivityArgs interface to give common functionality to all our implementations.

This enables us to directly .launch() into an Activity, or use args.intent() to pass around an intent for that Activity.

Flexible!

black box with pink, yellow, orange, grey, and green lines of code

Interface to give common functionality to all our implementations.

Next, we must implement ActivityArgs in a MediumProfileActivityArgs. This will require a strategy for serialization (intent.putExtra()) and a strategy for deserialization (intent.getExtra()).

black box with green, orange, light grey, yellow, pink, purple, brown, and dark blue lines of code

Kotlin data class that owns argument serialization and deserialization

Boom! We have a solution that is easily maintained — there’s one class that handles serializing and deserializing arguments for the MediumProfileActivity.

What about testing?

Super easy. Four steps.

  1. Create yourMediumProfileActivityArgs instance.
  2. Serialize instance into an Intent.
  3. Deserialize that intent.
  4. Verify de-serialized Args are equal to the original Args.

See the example below:

black box with green, grey, orange, yellow, light grey, and blue lines of code

A Kotlin data class allows easy assertions on equality

Conclusion

I firmly believe the above is a better approach to launching an Activity than the traditional YourActivity.launch(param1, param2) approach, which falls short in three ways:

  1. No deserialization. Requires additional code in onCreate() to deserialize (intent.getStringExtra()).
  2. Inflexible. What if you want an intent instance? You’d have add an overloaded method — YourActivity.intent(param1, param2). With ActivityArgs, just call args.intent().
  3. Harder to test. You would have to launch an activity to test deserialization

I hope ActivityArgs improves your development experience!


Zak Taccardi, Software Engineer, Android

Eat. Sleep. Android. 🤘

Related Content