Using Kotlin extensions to make the Android SDK friendlier

Colin White
tech-at-instacart
Published in
3 min readOct 16, 2018

--

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.

--

--