Kotlin as a first class language!

 
android_kotlin.png
 

This morning my wildest dreams came true - Kotlin became a first class language for Android development! This is exciting and it firms up what I've believed since the summer of 2015. Kotlin is the best language available to write native Android apps.

It's exciting because it means Google listens.

Pressure from developers has made it clear that Kotlin is where we see the platform going. It solves so many problems common to Android app development and brings features many developers lost hope of having. Method references, null data types, flexible control flows, lambdas, extension functions. There are plenty of libraries, hacks, and work arounds, but Kotlin brings consistency. The choice to support Kotlin means it will only get better and continue to flourish.

It's exciting because Kotlin can make you faster.

After the 1-2 days ramping up you find yourself accomplishing simple tasks in a fraction of the time it would have taken in Java. Language level features reduce ambiguity, drive readability, and make code more concise. You have first class nullability and you are forced to deal with it before you ship your app. It's as if JetBrains felt the pain of developing applications in Java and wrote a language to make it better (spoiler, they did.) You can see this throughout the language as you learn to write idiomatic Kotlin. You spend less time writing boilerplate (data classes anyone?) and more time writing interesting code.

It's exciting because it's rock solid on day one.

Years of testing and iteration before Google gave the green light has lead to a language and tool set that just works. It runs in your favorite IDE. It's works on every version of Android. Let me phrase this in another way - When was the last time you got an Android developer tool that just plain works. On day one. Like right now, go get it, and ship an app on the same day it was announced - 

This is the very first time and I hope this trend continues. Google doesn't need to invent everything and this proves that. They can be an amazing facilitator and still win. 

Clearly I am super jazzed about this and it's should be exciting for anyone who writes Android apps. You can check out my other Kotlin posts here and be sure to keep an eye out for more.

Kotlin Bricks: Using Android Extensions instead of ButterKnife

Kotlin Android Extensions is an add-on package and plugin that make it effortless to find a specific View in your layout. Similar to ButterKnife you don't have to write findViewById all over the place. That really where the similarities end and where Android Extensions really make your code (and work life) better.

To get started you need to add these to your module's ("app" in many cases) build.gradle file.

apply plugin: 'kotlin-android-extensions'

Now in your Activity, Fragment, or View subclass you can start accessing the strongly typed views in just two lines.

// add an import
import kotlinx.android.synthetic.main.YOUR_XML_LAYOUT_NAME.view.*

// access the view
tv.text = "Hello World!"

Thats it! There is no injecting, binding, or resetting anything. There is no casting. It's strongly typed so if it compiles, you won't get some runtime exception complaining about casting or a null pointer from a missing view.

Kotlin Bricks: When is better than If

One of my favorite things about Kotlin is the when expression. Its like a combination of an if and a switch you might be familiar with from Java. Performance is that of a standard if statement, , but it reads better and is more functional. Here is a quick example that handles specific values, ranges, and anything beyond.

val people = 10
when (people) {
    0 -> print("none")
    1 -> print("party of one")
    2 -> print("a couple")
    3, 4, 5 -> print("a few")
    in 6..12 -> print("a group")
    in 13..50 -> print("a gathering")
    else -> print("way too many")
}

My favorite ways to use when is to have it return a value based on a condition. Here is an example where I get a string based on the value of an enum.

val message = when (status) {
    Status.ONLINE -> R.string.connected
    Status.OFFLINE -> R.string.offline
    Status.CHECKING -> R.string.checking
    else -> R.string.unknown
}

Another way to use when is more like an if else statement. I generally don't use there because it can lead to comprehension issues. Here is an example where a mammal weighing more than 300 it would never reach the print statement, even though you might expect it to.

when {
    animal.isMammal() -> growHair()
    animal.isBird() -> {
        fly()
        makeNest()
        layEgg()
    }
    animal.weight > 300 -> print("make way")
}

Kotlin Bricks: One strategy to avoid nullable types

If you use Fragments, imagine this common situation where you passed values in via the appropriate setArguments call. The arguments bundle contains a model that you'll reference all over the fragment code. Grabbing it from the bundle every time could be messy and wasteful, especially if it never null.

var model:Bundle? = null
override fun onCreate(si: Bundle?) {
    super.onCreate(si)
    model = arguments.getParcelable("model")
    model?.getString("foo")
}

That might be your first approach, however every time you access model you'll need to dereference it with ? or !!. Since I guaranteed at the top that our app will always pass "model" in the Fragment arguments, we can do something slightly differently to avoid all of that.

val model by lazy { arguments.getParcelable<Bundle>("model") }
override fun onCreate(si: Bundle?) {
    super.onCreate(si)
    model.getString("foo")
}

By using lazy delegates we can make the model property non-null and use the Fragment arguments. This technique is useful in Android subclasses where you don't have much control over the lifecycle, but still want control over the nullability of your properties.

lazy works by waiting until the first time you access a property to actually assign it. This usually works well but you have to be cautious when you first call it. For example, calling the in constructor would cause a NullPointerException because arguments was not set yet.

Kotlin Bricks: Avoid lots of safe dereference using apply

Coming from a Java background its very common to null check quite a bit to avoid the billon dollar mistake. Kotlin solves this by introducing a null variant to every type so when you get the dreaded NullPointerException its probably a serious issue you should deal with. When starting out with Kotlin your instinct says drop ? everywhere, you know, just to be safe.

Consider this example where we did a good job to guard against a crash should onNetworkSuccess return after our UI has been destroyed. While simple, there are still three textView? and you could imagine it growing pretty quickly as you make a more complex UI.

var textView: TextView? = null

override fun onCreate(si: Bundle?) {
    super.onCreate(si)
    textView = findViewById(R.id.tv) as TextView?
}

fun onNetworkSuccess(message: String) {
    if (message.isNotEmpty()) {
        textView?.text = message
        textView?.visibility = VISIBLE
    } else {
        textView?.visibility = GONE
    }
}

As an alternative we can use the apply function to not only use the safe operator once but also avoid any unnecessary work if the view ends up being null. I think the code also read better this way.

fun onNetworkSuccess(message: String) {
    textView?.apply {
        if (message.isNotEmpty()) {
            text = message
            visibility = VISIBLE
        } else {
            visibility = GONE
        }       
    }
}