Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to add a custom listener to a Kotlin class

I'm a Kotlin noob (third day) and trying to add a listener to my class.

I'm currently using lambdas as in the following example and they work fine.

// Declare callback
class Controller {
   var onAction = { -> }
}

// Use callback
myController.onAction = {
   ...
}

However, I really like the way Android's Button::setOnClickListener is consumed in Kotlin code as follows (without having to use =):

myButton.setOnClickListener {
    awesomeObject.doSomething()
}

This makes me wonder:

How do I declare my listener so it can be used the Button::setOnClickListener way?

What is the most 'Kotlinic'(*) way? Mine or Button::setOnClickListener way?

(*) As in Pythonic :)

like image 286
El Marce Avatar asked Oct 31 '25 09:10

El Marce


2 Answers

You can use next syntax to add a custom listener:

class Controller {
    var onAction1: () -> Unit = {} // listener with default implementation without params and returns Unit

    var onAction2: (() -> Unit)? = null // nullable listener without params and returns Unit

    var onAction3: ((Int) -> String)? = null // listener with param of type Int and returns String object
}

Initializing listeners:

val controller = Controller()
controller.onAction1 = {
    // your action
}

controller.onAction2 = {
    // your action
}

controller.onAction3 = { intParam ->
    // your action
    "result" // return some String result
}

Calling listeners:

val controller = Controller()
controller.onAction1()
controller.onAction2?.invoke()
val result: String? = controller.onAction3?.invoke(20)
like image 174
Sergey Avatar answered Nov 02 '25 23:11

Sergey


fun setOnAction(block: () -> Unit) { onAction = block } and keep your onAction var.

But I suppose it's more Kotlin-idiomatic to just keep what you have. Properties are usually preferred over setter funs. The Android Button syntax is the result of SAM conversion of Java code. setOnClickListener ends up more concise than onClickListener = only because with the latter, the listener is a Java interface you have to name rather than a Kotlin function. It's really verbose to write:

button.onClickListener = OnClickListener {
    //...
}

so the SAM conversion is nicer to use.

like image 26
Tenfour04 Avatar answered Nov 02 '25 23:11

Tenfour04



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!