saulspatz
saulspatz

Reputation: 5261

Convert Function Call to Lambda (SAM)

In an android program, I have the following code:

clockCheckBox.setOnClickListener((object: View.OnClickListener {
    override fun onClick(view: View): Unit {
        if (clockCheckBox.isChecked())
            enableClocks()
        else
            disableClocks()
    }
}))

In Android Studio, a tooltip comes up that says,

This inspection reports an anonymous object literal implementing a java interface with single abstract method that can be converted into call with lambda expression.

I have tried to do this, but all I get is syntax errors. Can you show me the correct syntax? I should perhaps explain that this code is in the onCreate method of my activity and clockCheckBox is a local variable defined as

val clockCheckBox = findViewById(R.id.clockCheckBox) as CheckBox

Upvotes: 5

Views: 3307

Answers (3)

Les
Les

Reputation: 10605

It's useful to take a close look at the inspection report while understanding the conventions of Kotlin.

This inspection reports an anonymous object literal implementing a java interface with single abstract method (emphasis mine) that can be converted into call with lambda expression.

One of the keys in this report is "implementing a java interface with a single abstract method". This is key because anonymous objects implementing these kinds of interfaces can be succinctly written as just a lambda. In other words, you can skip the anonymous object literal and the name of the interface and just use a lambda that conforms to the single abstract method's signature.

In the case of the onClick, the equivalent signature is

    (view: View) -> Unit

So the lambda for your example would be

{ view -> if (clockCheckBox.isChecked) enableClocks() else disableClocks() }

But since you are not using 'view' in your lambda body, 'view ->' can be omitted. Instead of view, you are using clockCheckBox (which is a View in the closure for the lambda).

Lastly, when ever a function call's last parameter is a lambda, instead of writing

myFun( { ... } )

You can instead write

myFun { ... }

In other words, you are moving the last parameter, the lambda, outside of the parenthesis (the parentheses can be omitted if there is only one parameter). So your complete example using a lambda would be

clockCheckBox.setOnClickListener { 
    if(clockCheckBox.isChecked()) enableClocks() else disableClocks()
}

Upvotes: 5

holi-java
holi-java

Reputation: 30686

The code above can simplify as below:

//                v--- parentheses is unnecessary
setOnClickListener {
    //                        v--- boolean property parenthess is unnecessary
    if (clockCheckBox.isChecked)
        enableClocks()
    else
        disableClocks()
}

you can see Java Interoperability as further.

Upvotes: 3

Mibac
Mibac

Reputation: 9458

The way to convert it is to leave only the interface name and the code inside the function. A picture (example in this case) is worth a thousand words so that's how it'll look like:

clockCheckBox.setOnClickListener(View.OnClickListener {
    if (clockCheckBox.isChecked())
        enableClocks()
    else
        disableClocks()
})

You can read more about it on the kotlin docs page.

Upvotes: 2

Related Questions