Reputation: 1089
I tried to use method reference the same way as in Java:
button.setOnClickListener(this::clickListener);
Using Kotlin:
button.setOnClickListener {this::clickListener}
However this doesn't work in Kotlin, the solution is to actually invoke the function withing the labmda expression:
button.setOnClickListener {clickListener()}
Why Kotlin doesn't accept the method reference in this case? Isn't the same principle as with Java?
Upvotes: 2
Views: 6419
Reputation: 28228
Although this has already been answered, I'd like to expand the existing answers.
As TheWanderer already mentioned, curly braces here means the body of the lambda. Kotlin supports putting callbacks outside regular parenthesis.
This:
button.setOnClickListener {clickListener()}
Is equal to:
button.setOnClickListener({clickListener()})
which is equal to:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickListener();
}
});
Or (Java 8 only):
button.setOnClickListener(view -> clickListener());
TL;DR: contents of function arguments are defined with ()
, and lambda bodies are defined with {}
(just like with regular functions, classes, interfaces, etc.).
Now, first of all, a onClick method callback takes a view
argument. If you use a standalone function, it needs to have this argument:
fun clickListener(view: View) { TODO("Place your listener code here") }
This is based on the naming -- if you're implementing OnClickListener
, just pass this
as the argument. You already have the listener and function, so you don't need to explicitly define one to pass. However, if you do implement OnClickListener
, make sure to check the ID before taking action if you have multiple views using it as a listener.
If you are using methods, the next depends on how.
var
or val
functionsIf your callback is defined as:
val listener = {view: View ->
TODO()
}
You can pass it like an argument:
button.setOnClickListener(listener)
If you have a var onClickListener: OnClickListener
, the same as with var
/val
functions apply.
If you have a fun clickListener
, you'll have to add lambda to pass it. This is, just like with Java, using ::
. However, you don't need to explicitly declare the scope like in Java. Which means either of these will work:
button.setOnClickListener(::clickListener);
button.setOnClickListener(this::clickListener);
// alternatively with a different target, if it's somewhere else.
Upvotes: 7
Reputation: 17824
The curly braces denote the contents of the lambda expression. Kotlin has already passed an instance of an OnClickListener behind the scenes and is providing the onClick()
method to you.
If you want to pass a listener you have assigned to a variable, use parentheses:
button.setOnClickListener(clickListener)
If you want to use a function, it's the same as Java:
button.setOnClickListener(this::clickListener)
fun clickListener(v: View) {}
Upvotes: 5
Reputation: 547
You can do this in kotlin. Replace curly bracket with parenthesis.
btn.setOnClickListener (this::clicklistener)
fun clicklistener(v: View){}
Upvotes: 1