Playing around with Kotlin and Anko

 

Kotlin Language has been around for a while and recently matured to 1.0! There’s a lot of information out there explaining what modern language features Kotlin offers and what the benefits compared to good old verbose Java are, so I’m not going to cover those here. Instead I’ll be describing how to setup a Android project with Kotlin and Anko to see how a sample Kotlin Android app would look like, if it’s more readable and how much less boilerplate we have to write, since I was curious myself and just did. Let’s have a look, shall we?

 

First of all, tooling support in Android Studio for Kotlin is pretty good – as you would have expected, since the company driving Kotlin, JetBrains, are also the ones behind IntelliJ IDEA which Android Studio is based on. Not out of the box though, as of the time of this posting. You’ll have to install the Kotlin plugin that you can find under File | Settings ... | Plugins | Install JetBrains Plugins...

kotlin-plugin

After opening or creating a project, we’ll have to configure the project to use Kotlin by adding the kotlin-android gradle plugin, the kotlin-stdlib dependency. There’s a shortcut for this to have your module’s gradle build files fixed: Ctrl+Shift+A and start entering Configure Kotlin in Project :

kotlin-configure-project

The updated build.gradle file might then look something like this:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
[...]
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.2.1'
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    compile 'org.jetbrains.anko:anko-sdk15:0.8.3'
    compile 'org.jetbrains.anko:anko-appcompat-v7:0.8.3'
    testCompile 'junit:junit:4.12'
}
buildscript {
    ext.kotlin_version = '1.0.1-2'
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

where the dependencies to Anko are added manually. When you have .java files, we can have them converted to .kt files automatically – Ctrl+Shift+a | Convert Java file to Kotlin File. But that’s optional, since both Java and Kotlin files can coexist and be used together.

Now let’s write some code. We’ll create our activity by extending AppCompatActivity() and instead of having our UI layout described in XML and invoke setContentView(R.layout.activity_home) we’ll be using Anko’s DSL. Anko is a library containing a set of extension functions and properties to allow (as they put it) “Pleasant Android application development“. It comes with a DSL  that allows us to define our layout in a very condensed form. We’ll need eight input fields for our use case, along with eight labels, each of those go into a linearlayout to put weights on them to have them look aligned, and a viewgroup to put those in. And another scrollview on top. Here the whole thing:

scrollView {
    verticalLayout {
        padding = dip(16)
        layoutTransition = LayoutTransition()
        for (item in LineItem.values()) {
            verticalLayout {
                id = item.id
                orientation = LinearLayout.HORIZONTAL
                textView(item.labelResId).lparams(width = dip(0)) {
                    weight = 2f
                }
                editText() {
                    id = item.inputId
                    textAlignment = View.TEXT_ALIGNMENT_TEXT_END
                    inputType = InputType.TYPE_CLASS_NUMBER
                }.lparams(width = dip(0)) { weight = 1f }
            }.lparams(width = matchParent, height = dip(42))
        }
    }
}

Now let’s break this up. LineItem is an enum to iterate through. Topmost we have the scrollView  with contains a single verticalLayout (which corresponds to a LinearLayout and its naming is a bit misleading, since we also can have it layout horizontally as well) and within that are verticalLayout’s where we place our pair of label and input fields in. Despite the indentation being too high, I’m sure you’ll agree that this looks pretty readable. The equivalent XML layout file would look more bloated. Unless we would go for a recycler view with a reused list item layout, but that would result in some boilerplate code that we wouldn’t need.

Reading input from out EditText’s, parsing those as Float and defaulting to zero if nothing set is not the best example of using an extension function, but it’s saving us another couple of lines of code, since we’re doing it multiple times.

fun EditText.asFloat() = if (text.isNullOrBlank()) 0f else Integer.parseInt(text.toString()).toFloat()

As you can see, we’re adding the function asFloat() to the EditText  class – which allows us to invoke asFloat right on the EditText. When we define the extension function some place else, we would have to import it to use. Here we’re importing our extension function, read the inputs as Floats and creating our data model:

import com.ingloriousmind.android.propertyinvestortools.util.asFloat
[...]
fun parseInputToModel(): AssetData {
    val acquisitionCost = inputAcquisitionCost.asFloat()
    val purchaseRelatedCosts = inputPurchaseRelatedCosts.asFloat()
    val annualNetRent = inputAnnualNetRent.asFloat()
    val runningCosts = inputRunningCosts.asFloat()

    return AssetData(acquisitionCost, purchaseRelatedCosts, annualNetRent, runningCosts)
}

Which brings us to another nice feature that will save us a lot of boilerplate code: data classes. In our case this little one:

data class AssetData(var acquisitionCost: Float = 0f, var purchaseRelatedCosts: Float = 0f, var annualNetRent: Float = 0f, var annualRunningCosts: Float = 0f) {

}

Data classes in Kotlin saves us the need to generate setters, getters, hashCode, and equals functions and the need to create constructors and override toString. Lots of boilerplate code unwritten. Pretty neat.

 

Here’s how our little application looks like:

 

TL;DR

  • saves quite some boilerplate code
  • can mix and match Java and Kotlin files
  • android support
  • good tooling support
  • catch possible NPEs at compile time

Sources are available on property-investor-tools-android@Github. Obviously there are a lot more to Android development with Kotlin to discover. To get you started, there are some nice talks online worth checking out. E.g. this one by Svetlana Isakova:

 

Or this one by Jake Wharton:

 

 

Leave a Reply

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