Kotlin: My New Tool Of Choice
David Medina
David Medina

Kotlin: My New Tool Of Choice

David Medina, Android Engineer

I recently took the plunge during one of my company hack days, to finally give Kotlin a try. Kotlin is a statically-typed programming language that runs on the Java Virtual Machine and also can be compiled to JavaScript source code.

I found that code in Kotlin was cleaner, easier to write, easier to read, and was less error prone. It also felt like a huge burden off my shoulders to decouple myself from Google’s slow adoption of later Java features and relieved to no longer need back ports for features. I wanted to redo the same code test I completed to join Prolific in Kotlin – and complete it as if it was a serious project with an MVVM architecture and all the libraries I like to use.

I was blown away at how fun – that’s right, fun – it was to code in Kotlin. I’ll briefly walk you through some of my favorite features and discoveries I came across when working with Kotlin on that fateful day.

Libraries

I started by importing all the typical libraries that I would use on any normal Java project: Dagger, RxJava, Picasso, Retrofit, RxBinding. I discovered that RxBinding had a Kotlin version that exposes all the methods as extension functions, making it fit more naturally into a Kotlin application. I even included the Android data binding framework just because I thought that that would also be a good test of its supposed amazing interoperability. And I was not disappointed.

The only snag that I came across was not realizing initially that Kotlin had its own annotation processing compiler known as kapt. After adding that, everything just worked. Not only did the libraries I love still function, but I was able to remove a lot of libraries I used to have to import, such as Retrolambda and AutoValue.

Interop

I also experimented with using Kotlin classes in Java code and it all worked seamlessly. Sometimes it was obvious what was imported from Kotlin. However, there are things you can do to hide that, such as annotating packages and classes. This comes in handy if part of your app is done in Kotlin and you don’t want kt appended to some of the generated Java classes.

Community

Another point that was very surprising to me was that it seems there was already a robust community around Kotlin. Early on I had a question about best practices on setting up dependency injection with Kotlin and where and when to use lateinit; within an hour I had several posts on Reddit explaining what people believed was best and why.

Null Safety

When I started with Kotlin, I was writing it as if it was Java. I was over-usinglateinit and making fields nullable by marking them with ?. But having the? character everywhere made me rethink my code until I slowly started moving away from nullable variables and embracing the null safety Kotlin provides. I was a little shocked to find out how many I was able to remove. Ultimately, I was only using lateinit in places where I was injecting dependencies that I can’t inject via a constructor and using nullable on variables that were passed to me from Java classes since they could still be null.

Extension Functions

Another aspect of Kotlin I quickly embraced was extension functions. There was no need to compose any RxJava observables – I simply added a method to them they did the transformations for me.

At a later date I was experimenting with Anko, a library that adds a DSL for creating views as well as having ton of useful extension functions. I found myself creating time- and line-saving extension functions on views to streamline the integration of RxBinding and Picasso.

Design Patterns

There are some very useful design patterns that are built into Kotlin, removing all the boilerplate for making code very clean and concise. One is the delegation pattern – a pattern that’s close to my heart. Depending on the class that you’re delegating from, there could be a lot of boilerplate. However, by using the keyword by after declaring the implementation, you can automatically delegate the responsibility to another class without writing any of the interface methods.

Another pattern Kotlin reduces boilerplate for is the singleton pattern. By prefixing a class with the keyword object instead of singleton, Kotlin automatically creates the singleton for you.

We also use the keyword object to represent anonymous classes as well as static methods and properties

Data Classes & Named Parameters

Another major time-saver and line-saver I found was Kotlin’s data classes. If you declare a class as a data class, it automatically generates the toString,hashcode, equals, and copy methods for you. If you make all of its properties value types, which is the equivalent of final in Java, you basically have a value type without the need of the AutoValue library with a lot less lines of code. Because Kotlin supports named parameters and default values, it minimizes the need to create a builder for these classes. The copy method in conjunction with the named parameters make it easy to change only some of the values you are copying.

When you’re creating a class from scratch, you don’t have to worry about creating a ton of extra constructors. You basically write it once and get every variant of it for free.

In the above code sample I made the properties variable instead of value types simply because I want to see if it works with the Android two way data binding – which it does.

Delegated Properties

As I kept investigating Kotlin features that I could use to help improve the project, I took a look at delegated properties. Delegated properties are an easy hook into any property’s get and set methods that you could reuse. Two of the more interesting and useful looking ones that are built into Kotlin are delegate observables and lazy.

I’m not 100% sure it was best practice, but for the sake of experimentation, I delegated a boolean that controls whether the loading state was showing and used “by observable” so whenever the value updated the view would automatically be notified whether to show its loading state are not.

The other delegate property lazy allows you to describe how you want a variable initialized upfront, but does not actually initialize it until you first call it. This could be extremely handy if you have a very work intensive initialization but it might for a property that you may or may not use. Thus, you can avoid spending the CPU cycles until you absolutely have to.

Why Use Kotlin?

Since I created that first Kotlin app, I have been chomping at the bit to to use this in a large-scale project. I was shocked at how easy Kotlin was to write and read after not knowing anything about the language. Kotlin seems like a low risk/high reward upgrade to any Android project.

Kotlin code is more concise, readable and maintainable, and in a world where you spend so much time reading code, this alone is very powerful. The fact that NPEs throw errors at compile time instead of run time will mean a lot less crashes in production. The fact that JetBrains created it, and are using it in their products guarantees that there will be continued support for the language. This coupled with the fact that further Android support is in their roadmap, and they are the ones behind Anko, solidifies the fact that they plan to specifically continue to support Android developers. Since the interop with Java works so flawlessly, we don’t have to wait for an ecosystem to develop, as we can leverage the existing Java ecosystem; we can add it to existing projects bit by bit. Finally the fact that Jake Wharton, Android Open Source Celebrity, is also an evangelist of Kotlin gives me the confidence that Kotlin is a step in the right direction for entry-level developers.

One final thought: Google is slowly adding later Java version features to Android, but it seems to take them years to get this done. If Android developers don’t decouple from Java – by the time we have anything that looks like modern Java, we will be old and gray. We can add backports to our project, but I personally never feel good about it and I feel its getting out of hand. Kotlin could be the solution to this problem.