Reputation: 31
I have these both examples and I don't understand why you should use colon or curly braces
binding.playButton.setOnClickListener(
Navigation.createNavigateOnClickListener(R.id.action_titleFragment_to_gameFragment)
)
binding.playButton.setOnClickListener { view: View ->
Navigation.findNavController(view).navigate(R.id.action_titleFragment_to_gameFragment)
}
Upvotes: 0
Views: 648
Reputation: 19534
If it helps, View.OnClickListener
is an interface, so when you call setOnClickListener
you're providing an implementation of that interface:
binding.playButton.setOnClickListener(object: View.OnClickListener {
override fun onClick(p0: View?) {
TODO("Not yet implemented")
}
})
So in this example, you're creating an object (like an anonymous class) that implements the interface, with a body that includes the function you need to override. You're passing this object as a parameter in the setOnClickListener
method call. (This is basically what's happening in your first example, you're just calling another function to generate the object for you)
But because this interface only has a single function in it, you can strip this whole thing down to a lambda, which is like an anonymous function. So long as it matches the signature of the single function in the interface, it's accepted as an implementation!
binding.playButton.setOnClickListener({ p0 -> TODO("Not yet implemented") })
When it's a single argument like this, you can drop the variable name and it will just be called it
, if your code needs to refer to it at all (with more than 1 argument you'll need to explicitly name them though)
binding.playButton.setOnClickListener({ TODO("Not yet implemented") })
That function is held in the curly braces, it's a block of code. So we have both - the parentheses (because we're doing a method call), and the curly braces (delimiting the function we're passing to the method as an argument).
But Kotlin also lets us move a function parameter like this outside of the parentheses, if it's the last parameter in the call we're making. So if you're making a list of squares like this:
nums = List(4, { it * it })
you can move the initialisation function outside to make it neater
nums = List(4) { it * it }
and when the function is the only parameter, you can drop the parentheses entirely
nums.map { it * it } // equivalent to nums.map({it * it})
so that's what's happening with your second example - you're creating a lambda that's an implementation of the click listener interface, and passing it into setOnClickListener
, and because it's the only parameter you're dropping the parentheses and you're just left with the lambda in its curly braces
binding.playButton.setOnClickListener { TODO("Not yet implemented") }
hope that clears it up! The linter will usually give you some tips and quick fixes to clean things up to the preferred style
Upvotes: 1
Reputation: 602
simple answer is use braces {} to write a block of code (multiple lines) and use parentheses () to write a single line
Upvotes: 0
Reputation: 2705
First scenario - single click listener which should listen multiple views:
val clickListener = { view: View ->
when (view.tag) { // or view.id
// ...
}
}
binding.playButton.setOnClickListener(clickListener)
binding.pauseButton.setOnClickListener(clickListener)
Second scenario - listener which will be used only for one button:
binding.playButton.setOnClickListener { view ->
startPlaying()
}
Looks like you have some king of factory for listeners so first approach is preferable.
Upvotes: 1