· 4 min read

Lambdas in Kotlin, and how they simplify Android development (KAD 07)

Lambdas are one of the most powerful tools in Kotlin, and in any other modern language, since it allows modelling functions in a much simpler way.

The only way we can do this in Java 6 is by declaring interfaces with a single method, and creating anonymous objects that implement those interfaces.

Lambdas, and specially the way lambdas can be defined in Kotlin, open up an infinite world of possibilities. We will see some of these usages in the following articles.

Lambdas in Kotlin

A lambda is a way of representing a function, and we already saw an example of this when explaining the setOnClickListener:

val view = findViewById(R.id.welcomeMessage)
view.setOnClickListener { v -> navigateWithView(v) }

As you can see, the left side defines the input values of the function (in this case a view), and the right side declares the operation that function will perform.

How to define a function that accepts lambdas

If we wanted to define that function in Kotlin by ourselves, we would do the following:

fun setOnClickListener(listener: (view: View) -> Unit){}

This is known as a Higher-Order Function, because it is a function that receives a function by parameter, or that returns a function.

Kotlin and Java interop

The natural way of calling this function would be as follows:

view.setOnClickListener({ v -> navigateWithView(v) })

But we’ve already seen that there is a simpler way to do this, and that will also help us do very cool things that we will see right after.

This is because if the last parameter of a function is a function, we can extract it from the parentheses:

view.setOnClickListener(){ v -> navigateWithView(v) }

But in addition, if there is only one function as a parameter, we can just get rid of the parentheses:

view.setOnClickListener { v -> navigateWithView(v) }

DSLs creation

This allows us to create our own DSLs, which can define mini-languages. In Kotlin reference website there is an example with HTML, but here we are going to define an easier one.

Imagine that you want to create blocks of code that run on another thread. You could have a function that receives the function we want to run in the background:

fun doAsync(f: () -> Unit) {
    Thread({ f() }).start()
}

This function creates a thread that executes a Runnable which runs the function received as an argument. As Runnable is a class with a single method in Java, it can be substituted by a lambda in Kotlin.

Now we can create asynchronous blocks in our code:

doAsync { 
    op1()
    op2()
    op3()
}

Everything inside the braces will be executed in a secondary thread.

Inline functions

The ugly part of receiving functions as an argument is that the compiler needs to create classes for them, which can impact the performance. But this can be easily solved by using the reserved word inline.

An inline function will have less impact in performance because it will substitute the call to the function by its code in compilation time. So it won’t require the use of an extra object for this.

We can convert doAsync into an inline function:

inline fun doAsync(crossinline f: () -> Unit) {
    Thread({ f() }).start()
}

The crossinline in this case, is required because we are calling f() from another execution context (another lambda). Don’t worry about this too much, as the compiler will warn you when you need to use it.

If you want to learn more about inline, and also how it applies to the reified types concept, you can learn more about it in this video I recorded:

Conclusion

As you can see, with lambdas we can simplify our code a lot, and even achieve things that were impossible in Java.

In addition, Kotlin’s specific nomenclature makes it possible for us to create our own “language”, and create meaningful blocks of code that do what we need.

And if you want to learn how to use Kotlin to develop your own Android Apps, I recommend you take a look at my free training.

    Share:
    Back to Blog