Using Kotlin to make Android APIs fun again

Kotlin announcement at Google I/O 2017

If you haven’t heard, Kotlin is now a first class citizen on Android and we couldn’t be more thrilled at Basecamp. We’ve been using Kotlin since it hit 1.0 last year and we recently got to 100% Kotlin in the Basecamp 3 Android app.

One of my favorite features in Kotlin is extension functions. They let you extend functionality in classes without inheriting from them. We make great use of extension functions at Basecamp to simplify and add clarity to Android APIs that are verbose (or that we just don’t like). Below are a few example of ways that we leverage extension functions to make Android development easier on a day-to-day basis.

Set a View height

Setting the height on a View programmatically in Android is annoying (and I’m being nice). With a Kotlin extension, you can pretend that Android makes it easy for you:

fun View.setHeight(height: Int) {
val params = layoutParams
params.height = height
layoutParams = params
requestLayout()
}

Now when you want to set a height for your view instance, you just need to call view.setHeight(newHeight). Super easy!

Set View visibility

To make a view visible or gone by writing view.visibility = View.VISIBLE or view.visibility = View.GONE over and over is tedious. Never again! We have extension functions to make that nicer:

fun View.visible() {
visibility = View.VISIBLE
}
fun View.gone() {
visibility = View.GONE
}

Now we can just write view.visible() and view.gone() and… that’s it.

Read an Asset file into a String

Quick, how do you read one of your packaged asset file resources into a String? The answer is verbose input stream code. No thanks! We wrote an extension function:

fun AssetManager.fileAsString(subdirectory: String, filename: String): String {
return open("$subdirectory/$filename").use {
it.readBytes().toString(Charset.defaultCharset())
}
}

To retrieve the String, now we can write :

val json = context.assets.fileAsString("json", "config.json")

Retrieving a Color resource across API levels

Up until API 23, the way to retrieve a color resource was context.getColor(R.color.my_color). But starting at API 23, the signature added a new parameter for a theme resource. If you don’t need to specify a theme resource, you can make this easier on yourself so the same code can work on all API levels:

fun Context.color(@ColorRes id: Int) = when {
isAtLeastMarshmallow() -> resources.getColor(id, null)
else -> resources.getColor(id)
}

Now call context.color(R.color.my_color) anywhere you like and you have a clean wrapper. You could even make the theme resource an optional parameter with a default, since Kotlin supports this.

Inflate a Layout

Wish it was easier to inflate a new layout?

fun Context.inflate(res: Int, parent: ViewGroup? = null) : View {
return LayoutInflater.from(this).inflate(res, parent, false)
}

We can now write context.inflate(R.layout.my_layout) and avoid the mandatory parameters that Java required. (If you needed to attach your new view to the parent, you’d need account for that above.)

Use the Anko Library from JetBrains

JetBrains has already done a lot of work to make Android development easier. They’ve created many extension functions in their Anko library that you can use without writing any custom extension functions yourself.

For example, obtaining a System Service involves verbose syntax and error-prone type casting. With Anko it’s a lot easier:

val manager = context.notificationManager

That’s it. Under the hood, their extension property looks like this:

val Context.notificationManager: NotificationManager
get() = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

(Note that this is an extension property not an extension function — another great tool in Kotlin that you should explore.)

Android has many rich and powerful APIs, but they often cater to its legacy and limitations in Java. With Kotlin, you now have the power to shape the APIs you use most often. Imagine how nice it would be to be free of the API annoyances you’ve been living with for years!

I’d love to hear — what are some of your favorite extension functions that you’ve written for Android? Please share!

We’re hard at work making the Basecamp 3 Android app better every day (in Kotlin, of course). Please check it out!


Using Kotlin to make Android APIs fun again was originally published in Signal v. Noise on Medium, where people are continuing the conversation by highlighting and responding to this story.



[Read More …]

Leave a Reply

Your email address will not be published. Required fields are marked *