Search

An Introduction to Kotlin on Android

David Greenhalgh

6 min read

May 18, 2017

An Introduction to Kotlin on Android

Google I/O 2017 logo

Google surprised many at its 2017 I/O keynote by introducing Kotlin as a first-party language.
This day has been long-awaited at Big Nerd Ranch—we’ve been writing Kotlin apps internally and have fallen in love with its concise syntax and safety.
Now that Kotlin has the official seal of approval, let’s talk about what it can do for you.

What is Kotlin?

Kotlin is a JVM language developed at JetBrains, reaching 1.0 in February of 2016.
Up to this point, it’s primarily gathered steam in the Android community, providing relief to developers whose language growth had stagnated.

The first question people often ask about Kotlin’s introduction as an official language is, “Is this Android’s Swift?”
This is a natural reaction, given the similarity of their syntax and the relative recency of Swift’s unveiling.
I’ll leave the answer up to you, but Kotlin’s impact is worth considering as you decide which language to invest your time into.
If you’re interested in learning more about Kotlin, we’d love to help you out.

Your First Kotlin App

KlickerActivity.kt

In order to understand Kotlin, it may be useful to see it used to write an Android app.
We won’t touch on the syntax details of each line of code with a direct parallel in Java, but we will take a look at some of the more unique concepts.
Let’s look at KlickerHero, a small clicker game that I’ve written entirely in Kotlin for Android.

KlickerHero screenshot

Our only activity simply contains a TextView (with ID kounter) representing the player’s score and a button for the player to click repeatedly (with ID klicker).
To listen for click events and update the screen accordingly, we’ll need to obtain references to these views.
Let’s take a look at how we do this in KlickerActivity.kt.

class KlickerActivity : AppCompatActivity() {

    private lateinit var kounterTextView : TextView
    private lateinit var klickerButton : Button

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

        kounterTextView = findViewById(R.id.kounter) as TextView
        klickerButton = findViewById(R.id.klicker) as Button
    }
}

There are a couple of things to note here.
Let’s first look at kounterTextView and klickerButton.
One of the advantages of Kotlin is its null safety.
Every variable must be initialized in Kotlin, helping you avoid the pesky NullPointerException that plagues the lives of many Java developers.
This isn’t to say that variables can’t ever be null, but a variable that is assigned a null value must broadcast this state to any object that interacts with it.

In our case above, we bend the rule that variables should immediately be initialized by using the lateinit keyword.
lateinit is a contract stating that we can declare a variable without initializing it, but we’ll see an UninitializedPropertyAccessException if we try to use it before initialization.
It’s great for declaring member variables such as views in Android that need to be initialized in onCreate.

Kareer.kt

Our KlickerHero game is simple—click the button and your score goes up.
In order to really hook our players in, though, we need career progression.
We’ll track two statistics about our player:

  1. How many times they’ve clicked the button
  2. Which “tier” they’ve achieved based on their number of clicks

Let’s look at a simple Kotlin data class (with no Android code):

data class Kareer(var kount: Int = 0, var tier: Tier = Tier.Baby) {

    fun incrementKount() {
        kount++
        if (kount > tier.maxKlicks) {
            tier = getTierForLevel(tier.level + 1)
        }
    }
}

Kareer has two fields, kount and tier.
Classes in Kotlin can include constructor declarations directly in their header.
We can even define default arguments in case we aren’t passed a value for kount or tier.
Note that we declare kount and tier to be vars as a part of our constructor header.
This gives us member variable without any extra work.

Also note that Kareer is a data class.
Specifying a class as a data class in Kotlin gets us a number of method implementations for free, including equals/hashCode, toString, and more.

Kareer has one function, incrementKount.
When kount is incremented, we also want to check to see if the player has levelled up to a new Tier.
Let’s look at the player’s Tier, represented by an enumerated type:

enum class Tier(var level : Int = 0, val maxKlicks : Int, @ColorRes val kolorResId : Int) {
    Baby(0, 5, R.color.baby_blue),
    Novice(1, 15, R.color.light_green),
    Pro(2, 30, R.color.light_red),
    Master(3, 100, R.color.light_yellow),
    Grandmaster(4, Int.MAX_VALUE, R.color.grandmaster_purple);

    companion object {
        fun getTierForLevel(level: Int) : Tier {
            Tier.values()
                    .asSequence()
                    .filter { it.level == level }
                    .forEach { return it }

            throw IllegalArgumentException()
        }
    }
}

Enumerated types in Kotlin look pretty similar to other classes, and they may be familiar to Java developers.
One thing stands out against the rest of the implementation, and that’s the companion object keyword.
Companion objects are singletons declared within a class, and their usage is often similar to that of statics in Java.
In this case we’ve defined a method getTierForLevel that will return a Tier value for a specific level integer.

getTierForLevel could iterate through each value in Tier and return a value matching a specific value, but Kotlin provides functional constructs as a part of the language.
We won’t dig into them as a part of this post, but functional programming can be exceptionally useful when working with data.

Using our Kareer Model Object

Now that we have a data model expressed via the Kareer data class, let’s use it to display the user’s clicking prowess.

class KlickerActivity : AppCompatActivity() {
    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        ...

        val kareer = Kareer()

        klickerButton.setOnClickListener { updateKount(kareer) }
    }
    
    private fun updateKount(kareer: Kareer) {
        kareer.incrementKount()
        val tierColor = ContextCompat.getColor(this, kareer.tier.kolorResId)
        
        kounterTextView.apply {
            text = "Count: ${kareer.kount}"
            setBackgroundColor(tierColor)
        }
    }
}

In our KlickerActivity’s onCreate method, we’ll instantiate our Kareer object—no new keyword is necessary.
We’ll then set a click listener on the klicker button so that we update the count text and background color of the kounter TextView whenever the button is clicked.

The last niceties to introduce here are in the apply block.
apply passes whatever instance it is called on into a block in which you can sequentially invoke methods on it.
In this case, we call setText and setBackgroundColor on kounterTextView without repeatedly referencing kounterTextView.
It’s a sort of tiny scope change, and it’s great for invoking multiple methods on a single instance.

Lastly, note here that we directly assign to text rather than calling setText.
Getters and setters are hidden away from you with some syntactic sugar, saving you time spent writing and maintaining these methods.

What’s Next?

Google’s support of Kotlin solidifies a movement that was already building growing with significant momentum.
We can’t wait to see more people embrace Kotlin as a part of their everyday workflow in everything from small side projects to production applications at scale.

We’ve only scratched the surface in this post of what Kotlin has to offer.
We’ll be posting more blog content in Kotlin from here on. If you’re interested to learn more about Kotlin Programming, stay updated with our books & bootcamps.

Learn more about what Kotlin means for your Android apps. Download our ebook for a deeper look into how this new first-party language will affect your business.

Josh Justice

Reviewer Big Nerd Ranch

Josh Justice has worked as a developer since 2004 across backend, frontend, and native mobile platforms. Josh values creating maintainable systems via testing, refactoring, and evolutionary design, and mentoring others to do the same. He currently serves as the Web Platform Lead at Big Nerd Ranch.

Speak with a Nerd

Schedule a call today! Our team of Nerds are ready to help

Let's Talk

Related Posts

We are ready to discuss your needs.

Not applicable? Click here to schedule a call.

Stay in Touch WITH Big Nerd Ranch News