Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Store lambda in a variable in kotlin

I'm starting developing in Android with kotlin and I have a problem with lambdas. I have a function to set a listener in my view, this looks like this:

fun setListener(listener: () -> Unit) {
}

The problem is that the code passed as lambda won't be executed in setListener function, it will be executed in another part of my code (specifically when an item of a spinner is selected) so I have to "save" or "store" this lambda into a variable/property so that I'm able to execute it when needed. Any idea about how to do it?

Edit: I've achieved it by doing:

private var listener: (() -> Unit)? = null

fun setListener(listener: () -> Unit) {
    this.listener = listener
}

Is there a better way to do it? Thanks

like image 222
aloj Avatar asked May 05 '17 18:05

aloj


People also ask

How do you pass lambda as parameter Kotlin?

In Kotlin, a function which can accept a function as parameter or can return a function is called Higher-Order function. Instead of Integer, String or Array as a parameter to function, we will pass anonymous function or lambdas. Frequently, lambdas are passed as parameter in Kotlin functions for the convenience.

Can lambda function be assigned to a variable?

Creating a Lambda Function The lambda operator cannot have any statements and it returns a function object that we can assign to any variable.

How do you assign a function to a variable in Kotlin?

You can assign them to variables and constants just as you can any other type of value, such as an Int or a String . This function takes two parameters and returns the sum of their values. Here, the name of the variable is function and its type is inferred as (Int, Int) -> Int from the add function you assigned to it.

How do you use lambda in Kotlin?

A lambda expression is always surrounded by curly braces, argument declarations go inside curly braces and have optional type annotations, the code_body goes after an arrow -> sign. If the inferred return type of the lambda is not Unit, then the last expression inside the lambda body is treated as return value.


2 Answers

Here's how you can do it:

class Foo {
    private var listener: () -> Unit = {}
    fun setListener(listener: () -> Unit) {
        this.listener = listener
    }
}

However, manually writing setters is discouraged in Kotlin. Instead, you can just make your property public:

class Foo {
    var listener: () -> Unit = {}
}

For reference, here are the docs about properties with lots of examples.

like image 186
Christian Brüggemann Avatar answered Oct 10 '22 08:10

Christian Brüggemann


You can store a function in a property easily. The simplest way:

var listener: (() -> Unit)? = null

Usage:

foo.listener = { println("called") }

If you want your property to be set-only, you can create one public property with unusable getter and one private property for internal use. Full example:

class Example {

    // for internal use
    private var _listener: (() -> Unit)? = null

    // public set-only
    var listener: (() -> Unit)?
        @Deprecated(message = "set-only", level = DeprecationLevel.ERROR)
        get() = throw AssertionError() // unusable getter
        set(value) { _listener = value } // write-through setter

    fun somethingHappend() {
        _listener?.invoke()
    }
}
like image 24
Miha_x64 Avatar answered Oct 10 '22 07:10

Miha_x64