Using Kotlin extensions to make the Android SDK friendlier
It’s no secret that the Android SDK has a few rough edges.
Imagine that you’re new to Android and trying to display an image. You’ve already added the image to your res
folder and now you need to get a Drawable
. You write outresources.getDrawable()
only to find it’s deprecated and the function it’s replaced by is only available on Lollipop and above. What do you do if you need to support pre-Lollipop? If you’re like me a few years ago, you end up writing your first (of many)if (SDK_INT >= LOLLIPOP)
blocks.
Ideally, I would know about ResourcesCompat, AppCompatResources, or ContextCompat which act as Utils
classes to bridge the gap between platform API changes. However, these classes aren’t nearly as discoverable as having Android Studio autocomplete getDrawable()
.
Kotlin extension functions allow for better discoverability and more fluent APIs vs. traditional utils classes by “adding” new methods to existing classes. Android Studio will autocomplete these methods and they aren’t tied to a specific version of the Android platform SDK. Additionally, their implementation can be changed as the platform evolves.
This is why Google recently introduced Android KTX. The set of libraries seek to make the Android SDK more intuitive by leveraging Kotlin language features (such as extension functions).
With that said, I want to share a few of my favourite Android extension functions that are not part of Android KTX:
pxToDp / dpToPx
Simplify interoperating between Dp
and Px
.
E.x. 2.pxToDp()
4.dpToPx()
getColorCompat / getDrawableCompat
Calling back to the example above, these extensions optimize for discoverability. They only act as aliases for the Android X compat functions.
E.x. context.getColorCompat(R.color.green)
context.getDrawableCompat(R.drawable.vector)
tint
tint
can be used to tint drawables across all API levels by delegating to Android X.
E.x. getDrawableCompat(R.drawable.circle).tint(Color.Black)
inflate
Simplify the common operation of inflating a child view without adding it to its parent.
E.x. val view: CustomView = parent.inflate(R.layout.custom_view)
unsafeLazy
By default, Kotlin’s lazy
function uses a thread-safe lock to ensure the initialization code is only run once. For variables that are only accessed from a single thread (like the main thread), we can avoid using a lock to improve performance. unsafeLazy
is an alias for this implementation.
E.x. val green = unsafeLazy { getColorCompat(R.color.green) }
toActivity
Traverse the Context tree to find the nearest Activity.
openWebPage
Open a web page using Chrome Custom tabs or fallback to another browser if Chrome is not available. Note: You’ll need to add androidx.browser:browser
to your Gradle build file.
E.x. context.openWebPage("www.instacart.com")
I’ve compiled all these extensions here, if you’d like to add them to your project. Also let me know your favourite extension functions in the comments!
Find this interesting? Come join us; Instacart is hiring! Feel free to reach out to me on Twitter (@colinwhi) with any questions/comments/feedback or to just to say hi 👋.
Thanks to Jon Hsieh for editing this article.