Starting Activities with Kotlin — My Journey
This is a reaction to the article You won’t believe this one weird trick to handle Android Intent extras with Kotlin by Eugenio Marletti. It reminded me at my first attempts to make the
startActivity API better by using the Kotlin feature
Extensions. This article describes different solutions to start Activities because we don’t have static methods in Kotlin to build our loved
Regarding Eugenio Marlettis article and his library, I must admit, I never heard of the concept of putting static getters/setters on the
Activity class to manipulate an
Intent. It also doesn’t sound useful to me. I’ll most likely never use it but I’m very happy to see Kotlin libraries specifically targeting the Android community.
newIntent() in Java
newIntent method for Activities is an alteration of the
newInstance method for Fragments which is even part of the official Fragment documentation.
newIntent isn’t official but a logical step for Activities which is widely used.
This is how it looks in pure Java:
Intent is build inside the UserDetailActivity and not outside. You cannot make it wrong and accidentally forget an extra. Also notice that the constant for the key is
Now let’s translate this to Kotlin! When you’re new to Kotlin you’re maybe interested in a 1:1 translation which I’ll improve later on.
Because kotlin has no static fields a companion object is used, a single shared object between all instances of the hosting class.
Because tried to be a “clever guy”, new to Kotlin and in love with all the new possibilities I tried to use them all at once and created cool extension functions to launch Activities. You can’t find them here when you’re interested. The implementation isn’t that interesting, I’ll just show you how it works:
Isn’t it cool? Here are some noticeable facts:
- less code, full flexibility than starting Activities the normal way
- one method (
launchActivty) used for everything, no
launchActivitymethod is only available in
Contextclasses, and the override with the
requestCodeonly works for
What I don’t like:
Intentconstruction not within the Activity file and the extra name const is public
- not “type safe” like the
newIntentmethod from Java
It’s nothing more than a better
Moving the launch function to the Activity file
Then I started to get crazy and created overrides of this
launchActivity method for every
Activity to move the
Intent construction to the correct file.
Nailed it! Everything is scoped as in Java, it’s not possible to forget an argument, as in Java. 🎉
I lost functionality compared to simply calling the extension function
launchActivity(). I didn’t create an override for both extension functions, the
Activity and the
Context extension. So I can’t call
launchUserDetailActivity() with a
requestCode. And because the
Activity will be launched directly I cannot use the generated
Intent to use
And it’s a lot code, I don’t want to write all this for all Activities. I also had copy past errors and after all I cannot recommend doing it this way. But it’s a nice demonstration that it can be better to go one step back.
My current best practice
I stopped using the
launchActivity method. I went back to use
startActivity and the already existing overrides. This also makes it easier for new people to Kotlin. They can search the code for “startActivity” and find the correct spot where the Activities are connected. This is a big win.
My Intent builder function is still an extension function for
Context. I still pleased with the decision. It only might get messy when you have dozens of those methods.
- I moved the extra key constant
INTENT_USER_IDout of the Activity. In all languages you define constants outside of a class. It’s different in Java, because it’s not possible to define anything outside of a class.
UserDetailIntent(User)method is now an extension method. This restricts the visibility of this method to classes and objects where you can actually use this method. When you have a bad feeling about the uppercase method name, read this and feel free to change it.
apply()practically speaking replaces builders in Kotlin. It returns the target object after it’s configured within the lambda.
The good parts:
- Intent creation and parsing is all within the Activity file
- the Intent construction method doesn’t require setting the
- it can only be called in or on
- you can define optional parameters i.e.
inEditMode: Boolean? = false
- no companion object is used which requires some boilerplate code to mimic “static” methods we know from Java.
The bad parts:
- no universal name such as
What you do think about my methods to start Activities? I excited to get your feedback or tips to improve those methods even further. Hit me on Twitter for suggestions