Making Safer Apps with Kotlin

Written by: on April 7, 2016

The more programming languages I learn, the more I see the benefit of high level expressive languages on code quality and maintainability. Fortunately I am not the only one. New modern and safe languages are gaining traction. On desktop and servers, Rust is gaining momentum. On iOS, Swift is taking the world by storm. And for the Java/Android world, Kotlin is a new contender that we should give a chance.

Non-Null by Default

Above all else, I like Kotlin because variables are not nullable by default. NullPointerExceptions are the bane of developers everywhere and the cause of way too many preventable bugs. In Kotlin, things that can be null are marked on the type level, and unlike annotations, trying to set a non-nullable value to null will result in a compile error. With val list = listOf(1,2,3,4,5) you know that list will always be a valid reference, without fear of a null value. When you do need to mark a value as potentially null, you mark it with the type: var list: List? = null. ? after a type means it is a nullable value, and with it, it means you need to check if it is null before using it. Failing to make sure a nullable value is valid is a compile error. The old style check for null works:

However, it’s more idiomatic Kotlin to use the more streamlined syntax size = list?.size?: 0 This workflow has two benefits. When a reference can be null, ? gives us a convenient no-op instead of a crash and more importantly lets us feed a default value if something doesn’t exist.

This becomes particularly useful with collections when grabbing an index or a key. As part of unwrapping the nullable value into a real value, you can provide a default or an error case to display in your adapter instead of crashing and killing the entire app.

While handling nulls safely like in my examples above is recommended, there is another feature of nullable values called a force unwrap. Marked by !!, This will return a value if it exists or trigger a NullPointerException. Remember with great power comes great responsibility. This should almost never be used but it is good to know it exists. Here is a sample usage:

Android Integration

My second favorite feature is how it deals with Android layout integration if we have the the android plugin enabled. Say we have an item in our layout that looks like this.

To change the text with Kotlin, write helloWorldText.text = "こんにちは、世界"

Thats it! Its that simple. Enable one plugin and Kotlin will handle finding the view and returning it as the proper type.

Expressions:

Another great feature of Kotlin is if and try are expressions instead of statements. This means we can assign a value from the result of an if expression or a try catch block directly. Lets use parsing JSON as an example. Say our network request should return a list of integers such as [1,2,3,4] we then want to feed that to our JSON parser. Using Gson it would look something like:

However this can throw an exception. Say the data provider returns the wrong data and now it is sending back strings “[“A”, “B”, “C”, “D”]”. When Gson tries to parse this, an exception will be thrown and the app will crash. So we want to put it in a try catch block.

This is much better. Not only do we handle the exception and avoid crashing, we can provide an alternate list (in this case, an empty list) so our data layer can continue as normal. If statements work exactly the same way:

Lambdas

Lambdas go a long way to writing clean code. Lambdas allow us to define an anonymous function in place, even storing that function as a variable or passing it as a parameter to a function. Kotlin has lambdas built in and Kotlins standard library is designed to take full advantage of them.

One of my personal favorites is for filtering a list.

Here is our data set before and after applying the filter.

Kotlin1Kotlin2

This use for filtering and sorting collections makes our code so much cleaner. It is so much nicer to just give it a function instead of having to implement comparable on my custom data type.

Not to mention the ever common setting a click listener on a button. This cleans up all the boilerplate normally required for making a new OnClickListener.

Being able to pass functions as a parameter to other functions is incredibly powerful.

Java Integration

As for Java integration, the whole thing Kotlin is able to interface with Java without much hassle. Calling things from Java classes works automagically and it treats returned data as nullable since Java has no promises of null safety without adding explicit annotations. Better yet, you can call Kotlin code from within your Java code easily. Mix and match as you see fit. When working with a long running existing Java codebases, I recommend starting the transition with the data layer, handle your data safely and work your way up to your adapters, fragments, and activities.

As an example I wrote up an Activity in Java that calls my Adapter and Data which are Kotlin classes.

This looks just like you would expect with any Android app. Now lets look at the adapter.

And the fancy data:

As you can see, this is clearly not Java code and yet the Java code and the Kotlin code all work together. The KotlinAdapter extend RecyclerView.Adapter which is a Java class. The JavaActivity creates a RecyclerView that uses an instance of KotlinAdapter as the adapter. It binds ViewHolders that are KotlinViewHolder which extend RecyclerView.ViewHolder and use FancyData which are pure Kotlin data classes. This all works together quite seamlessly.

Thats it for some of the features. Now lets walk through setting it up in Android Studio.

Setting up Kotlin

Step one is installing the plugin. Inside the preferences go to plugins:

Kotlin3

Then search for “Kotlin.” Have Android Studio install that plugin and restart. There is no need to install the extensions for android, those have been merged with the Kotlin plugin.

Kotlin4

After Android Studio restarts, either create a new project or open an existing project you wish to use.

Under tools there is a Kotlin section. Select configure Kotlin in project.

Kotlin5

Kotlin6

Then in your build.gradle for your app add apply plugin: 'kotlin-android-extensions' This lets us use fancy xml data binding like the example of changing text from above.

From here you can create new Kotlin files and extend from Androids classes such as Activity. Then just continue building great Android experiences as normal, but with an extra twist of Kotlin in the mix. Or you may convert existing Java classes to Kotlin under the code menu.

Kotlin7

In my experience, this for the most part just works. The big thing to keep in mind is when its finished, convert forced unwraps to actually handle your null cases and fix any other errors you have from places it couldnt convert properly like when it is unable to infer a generic type correctly.

The Downsides

As much as I love working with Kotlin and as much as I think it should be used, I will try my best to give an unbiased list of downsides and why you may not want to use it on a project.

  • Kotlin is not officially endorsed by Google (this is no longer true as of Google I/O 2017). Currently this isn’t a problem and shouldn’t be a problem anytime in the near future. However on the off chance Google decides the Android toolchain will no longer be Java bytecode compatible, Kotlin will likely no longer be an option
  • New Syntax: While the syntax is not different enough to cause major struggles, there is a slight hit to productivity as there is with learning any new language.
  • The Kotlin Standard Library and runtime does add a small amount to the APK. Somewhere around 800 KB but if your APK is large enough where every little bit counts, this may not be for you.

Thats all for now. If you are interested in the full working sample, please checkout the code at https://bitbucket.org/eyoung/kotlin-insights-example.

Eric Young

Eric Young

Eric is a developer at POSSIBLE Mobile. Eric develops Android apps by day, hacks on Rust programs by night, and constantly tries to find ways to make his code more maintainable.
Article


Add your voice to the discussion: