Kotlin setOnClickListener syntax using lambda

When setting up a click listener in Kotlin, we can write:

rollButton.setOnClickListener(
    object: View.OnClickListener {
        override fun onClick(v: View?) {
            rollDice();
        }
    }
)

After SAM conversion, we can write:

rollButton.setOnClickListener({ v -> rollDice() })

But I noticed that kotlin also accepts:

rollButton.setOnClickListener(View.OnClickListener() { v -> rollDice() })

as well as

rollButton.setOnClickListener(View.OnClickListener { v -> rollDice() })

I want to know what is happening here? I mean setOnClickListener is supposed to take an implementation of OnClickListener using something like Anonymous class or SAM shorthand. Is this some kind of intermediate stage or what?

Any explanation or link to resources is highly appreciated.

Answer

For these examples, let the interface be:

fun interface IntUser {
    fun use(value: Int)
}

SAM conversion lets you use the interface’s name like a constructor that takes the lambda as an argument.

val x = IntUser({ println(it) })

Trailing lambda syntax allows you to move the lambda outside the parentheses like your second example:

val y = IntUser() { println(it) }

When using trailing lambda syntax when the lambda is the only parameter, you can omit the parentheses, like in your third example:

val z = IntUser { println(it) }

Finally, the other thing SAM conversion can do is let you pass a bare lambda in place of an interface parameter. It can infer the type from the function argument:

rollButton.setOnClickListener {
    rollDice()
}

Here we are using the lambda as the sole parameter, so we are also employing trailing lambda syntax and omission of the empty parentheses.

Leave a Reply

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