Alejandro Agüero
Alejandro Agüero

Reputation: 31

When do write inside () or {} on setOnClickListener? Android Studio

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

Answers (3)

cactustictacs
cactustictacs

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

ElMobark
ElMobark

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

Mike
Mike

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

Related Questions