I’ve been hearing about Kotlin everywhere. It’s the new big thing in the Android world. So big that Gradle themselves are talking about incorporating it.

So I set out on a journey to see what the hype is all about.

What is Kotlin? Well, simply put it’s a statically-typed language from the house of JetBrains that compiles to Java’s bytecode and therefore can be run using a JVM. It’s got lots of interesting features and full compatibility with Java.

The following post is not a conventional Hello World tutorial on Kotlin, rather it’s an experiment with a big bold “don’t try this at home” warning. It’s risky and code might break because I’m going to convert a whole project of a mid-level complexity (30 classes) at the click of a button, or rather 4 buttons (ctrl + alt + shift + k). If that won’t work out (spoiler alert: it didn’t), I’ll switch to plan B and convert my project one class at a time.  I’ve decided to see if they’re making good on their promise, as well as teaching myself a new programming language upside down. From big concepts to the finer details.

Because I’m going to mess with lots of code and it might not end up pretty I chose to convert one of Android’s google-samples projects which I forked. I chose the todo-mvp branch: https://github.com/SerjSmor/android-architecture. If you are unfamiliar with different styles of Android architecture (MVC, MVP, MVW) or their implications I highly recommend going over them anyway if you haven’t yet.

TL;DR: we’re converting a TODO List app.

Environment:

IDE = Android Studio 2.1.2. There’s a plugin for Eclipse too.

Kotlin version = 1.0.4

The before photo (before tinkering):

Hello, Kotlin! How to Convert an Android Project – Part 1

Installation

1. Download Kotlin plugin (let the .gif show you how)

Hello, Kotlin! How to Convert an Android Project – Part 1

2. Configuring the plugin (another gif)

Hello, Kotlin! How to Convert an Android Project – Part 1

You’ll be asked to configure ‘Gradle’ or ‘Android with Gradle’. I chose the latter because the ‘gradle.build’ file that it configured matched other Kotlin projects around and was similar to Kotlin’s gradle docs.

Kotlin conversion

To convert a class, or several classes use either method:

  • Highlight a class and use key shortcut: ctrl + alt + shift +k.
  • Choose the “Convert Java File to Kotlin File” from the “Code” options menu bar.

Converting a Whole Project at Once

Select the app/src/main/java folder, and choose to convert to Kotlin (or use the magic ctrl+alt+shift+k shortcut). You should get a pop-up which reads:

Some code in the rest of your project require corrections after performing this conversion. Do you want to find such code and correct it too?

In my case, clicking ‘OK’ has led to Android Studio throwing an exception:

Kotlin threw an uncaught StackOverflowError

Thankfully, it didn’t crash, but it shows some things aren’t yet configured properly. If you have encountered somewhat a different experience please contact me and tell me about your experience.

Time to see the damage.

AddEditTaskActivity compilation error

Suddenly a wild compilation error appears. Intellij points to AddEditTaskActivity’s onSupportNavigateUp() method:

val countingIdlingResource: IdlingResource
       @VisibleForTesting
       get() = EspressoIdlingResource.getIdlingResource();

The last line shows the compilation error:

Unresolved reference: getIdlingResource.

We will resolve this issue, but first let’s compare both old and new AddEditTaskActivity.

AddEditTaskActivity code changes outline

Java Code

public class AddEditTaskActivity extends AppCompatActivity{

      public static final int REQUEST_ADD_TASK = 1;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
             //….
      }

     @Override
     public boolean onSupportNavigateUp() {
               onBackPressed();
               return ture;
     }

     @VisibleForTesting
     public IdlingResouce getCountingIdlingResource() {
                return EspressoIdlingResource.getIdlingResource();
     }
}

Kotlin Code

class AddEditTaskActivity : AppCompatActivity() {

     override fun onCreate(savedInstanceStats: Bundle?) {
              //….
     }

     override fun onSupportNavigateUp() : Boolean {
            onBackPressed()
            return true
     }

     val countingIdlingResource: IdlingResource
          @VisibleForTestnig
          get() = EspressoIdlingResource.getIdlingResource();

     companion Object {
          val REQUEST_ADD_TASK = 1
     }

}

Semicolons: Kotlin doesn’t mandate semicolons. That’s the first step towards Kotlin’s attempt to reduce Java verbosity.

Function declaration: keywords ‘override’ and ‘fun’, are straightforward. Putting the return type after the method name is not.

override fun onSupportNavigateUp() : Boolean

First comes the method name then the return type, separated by a colon ‘:’. Got it. More on function declarations can be found here.

Function parameter declaration

Function parameter declaration: Again, we meet the colon before the type.

override fun onCreate(savedInstanceStats: Bundle?) {}

Nullability: Kotlin decided to help us devs with our NullPointerExceptions. How? With the call safety operator ‘?’ of course. Kotlin mandates we declare which class members, variables and parameters can be null or not. Declaring ‘Bundle?’ in previous snippet implies that saveInstanceState might be null, hence a good well educated programmer must first make the appropriate check.

Yes, the following with result in a compilation error:

override fun onCreate(savedInstanceStats: Bundle?) {
           savedInstanceState.get(SOME_KEY);
}

But doing a lot of “if (savedInstanceState != null)” is kind of ugly. So Kotlin’s ? is there for us again:

override fun onCreate(savedInstanceStats: Bundle?) {
           savedInstanceState?.get(SOME_KEY);
}

In case saveInstanceState reference is null, the method get() will not be called and the line would produce a null. This operator can be chained and removes a whole bunch of if-else blocks.

I think this feature was influenced by many existing languages, Swift included. This is one of the main strengths of Kotlin, trying to improve NPE cases. Android added @Nullable annotations dealing with the same issue, through the android.support.annotation library.

Companions – Kotlin’s static members and functions: Without going into too much detail, let’s just think of a companion like we do with Java’s statics.

companion object {
     val REQUEST_ADD_TASK = 1
}

You may also access companion members and functions using the class name followed by “Companion” with a dot notation, just like Java static.

part(‘Class.Companion.func()’)

Companion objects are helpful when implementing Singleton patterns and various factories. More on this here.

Val and var – Kotlin’s mutable and immutable variables

Val vs. Var – Kotlin’s mutable and immutable variables: ‘val’ are constant values while ‘var’ are variables.  And note – you don’t need to declare a class type. It’s part of Kotlin’s magic. Kotlin infers the type of the variable by the type of the initializer.

val REQUEST_ADD_TASK = 1

Here REQUEST_ADD_TASK is set to the constant value ‘1’ so Kotlin infers that it’s an integer.

SafeDK Data shows 0.25% of Apps are already using Kotlin (or one of their SDKs is using it). Find out more!

Are we there yet?

Right now we’re already halfway through, and it wasn’t that bad, wasn’t it? But we still can’t compile and we have an error we haven’t dealt with yet.
Let’s proceed to onCreate():

override fun onCreate(savedInstanceState: Bundle?) {
     super.onCreate(savedInstanceState)
     setContentView(R.layout.addtask_act)

     // Set up the toolbar
     val toolbar = findViewById(R.id.toolbar) as Toolbar
     setSupportActionBar(toolbar)
     var actionBar = supportActionBar
     actionBar!!.setDisplayHomeAsUpEnabled(true)
     actionBar.setDisplayShowHomeEnabled(true)
}

What’s that all about?

‘as’ keyword – for all your casting needs

The ‘as’ keyword (for all your casting needs): If you don’t like Java parenthesis casting, Kotlin has a special ‘as’ keyword for casting just for you

val toolbar = findViewById(R.id.toolbar) as Toolbar

Append the previous mentioned safe call operator ‘?’ to get a safe cast, and avoid ClassCastExceptions:

val toolbar = findViewById(R.id.toolbar) as? Toolbar

More on this here.

Nullability: ‘!!’ if you badly want Null Pointer Exceptions throwing around

Nullability Vol.2 – the ‘!!’ operator for when you want NPEs running around: So what do you do when you have a variable that might be null and that’s maybe okay? You let Kotlin know you live on the edge by specifying not one but two exclamation marks (!!).

actionBar!!.setDisplayHomeAsUpEnabled(true)

In case actionBar is null, a NullPointerException will be thrown. More on this, here.

Fixing the Compilation Error

Now it’s time to solve the compilation error we had. Let’s take a look at the Java “source” first:

public IdlingResource getCountingIdlingResource() {
     return EspressoIdlingResource.getIdlingResource();
}

Which was turned into:

val countingIdlingResource: IdlingResource
  get() = EspressoIdlingResource.getIdlingResource();

In Kotlin, class members can have a custom getter/setter for properties, like the get() we’re seeing here.

But what’s the problem? Let’s look at the EspressoIdlingResource class now.

Java Code

public class EspressoIdlingResource {
     //…
     public static IdlingResource getIdlingResource() {
                return mCountingIdlingResource;
      }
}

Kotlin Code

object EspressoIdlingResource {
     //..
     val idlingResource : IdlingResource
          get() = mCountingIdlingResource
}

idlingResource is a property, and it has a custom getter. The error is due to the mismatch of getters that happened during the Kotlin conversion.

If you’re all “What you’re talking about, Willis?” right now, allow me to clarify:

  • getIdlingResource() is a static method in EspressoIdlingResource class
  • idlingResource is a property
  • Kotlin’s way of accessing getters of properties is by their name

So the fix would be to simply not use the getter, but rather access the immutable property directly:

get() = EspressoIdlingResource.idlingResource;

And that’s it. Case closed. Class compiles.

SafeDK In-App Protection

So Project Compiles?

Up until now I learned how to configure Kotlin in a project and some of Kotlin’s new features and syntax. Treading lightly around nulls. The difference a letter makes when defining a var or a val. And really screaming at Kotlin – !! – that I’m a risk-taker.

I’ve even tackled some compilation problems head on, dug deep and found the solution.

But I’m afraid I have some bad news. After fixing this one error, I still had some 20+ errors coming up. I’ve come to the conclusion that this approach isn’t feasible. It’s not such a surprise I guess, converting the whole project at once was a longshot due to the complexity of the task. I was asking for trouble really. 30 classes and dependencies are a tough nut.

But I didn’t give up just yet. In my next installment I’ll show you a class by class approach and some final words about the whole experience including some metrics. Stay tuned!