J'ai ces deux exemples et je ne comprends pas pourquoi vous devriez utiliser deux points ou des accolades

  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)

    }
0
Alejandro Agüero 23 sept. 2020 à 22:49

3 réponses

Meilleure réponse

Si cela vous aide, View.OnClickListener est une interface, donc lorsque vous appelez setOnClickListener, vous fournissez une implémentation de cette interface:

binding.playButton.setOnClickListener(object: View.OnClickListener {
    override fun onClick(p0: View?) {
        TODO("Not yet implemented")
    }
})

Donc, dans cet exemple, vous créez un objet (comme une classe anonyme) qui implémente l'interface, avec un corps qui inclut la fonction que vous devez remplacer. Vous passez cet objet en tant que paramètre dans l'appel de la méthode setOnClickListener. (C'est essentiellement ce qui se passe dans votre premier exemple, vous appelez simplement une autre fonction pour générer l'objet pour vous)


Mais comme cette interface ne contient qu'une seule fonction, vous pouvez réduire tout cela en lambda, ce qui est comme une fonction anonyme. Tant qu'elle correspond à la signature de la fonction unique dans l'interface, elle est acceptée comme implémentation!

binding.playButton.setOnClickListener({ p0 -> TODO("Not yet implemented") })

Quand il s'agit d'un seul argument comme celui-ci, vous pouvez supprimer le nom de la variable et il s'appellera simplement it, si votre code doit y faire référence (avec plus d'un argument, vous devrez les nommer explicitement bien que)

binding.playButton.setOnClickListener({ TODO("Not yet implemented") })

Cette fonction est maintenue entre accolades, c'est un bloc de code. Nous avons donc les deux - les parenthèses (car nous faisons un appel de méthode) et les accolades (délimitant la fonction que nous transmettons à la méthode en tant qu'argument).


Mais Kotlin nous permet également de déplacer un paramètre de fonction comme celui-ci en dehors des parenthèses, si c'est le dernier paramètre de l'appel que nous faisons. Donc, si vous faites une liste de carrés comme ceci:

nums = List(4, { it * it })

Vous pouvez déplacer la fonction d'initialisation à l'extérieur pour la rendre plus nette

nums = List(4) { it * it }

Et lorsque la fonction est le seul paramètre, vous pouvez supprimer entièrement les parenthèses

nums.map { it * it } // equivalent to nums.map({it * it})

C'est donc ce qui se passe avec votre deuxième exemple - vous créez un lambda qui est une implémentation de l'interface d'écoute de clic, et vous le passez dans setOnClickListener, et parce que c'est le seul paramètre, vous laissez tomber les parenthèses et vous êtes juste laissé avec le lambda dans ses accolades

binding.playButton.setOnClickListener { TODO("Not yet implemented") }

Espérons que cela clarifie les choses! Le linter vous donnera généralement des conseils et des solutions rapides pour nettoyer les choses selon le style préféré

0
cactustictacs 24 sept. 2020 à 00:25

La réponse simple est d'utiliser des accolades {} pour écrire un bloc de code (plusieurs lignes) et d'utiliser des parenthèses () pour écrire une seule ligne

0
ElMobark 23 sept. 2020 à 22:04

Premier scénario - écouteur en un seul clic qui devrait écouter plusieurs vues:

val clickListener = { view: View ->
        when (view.tag) { // or view.id
            // ...
        }
    }
binding.playButton.setOnClickListener(clickListener)
binding.pauseButton.setOnClickListener(clickListener)

Deuxième scénario - auditeur qui ne sera utilisé que pour un bouton:

binding.playButton.setOnClickListener { view -> 
     startPlaying()
}

On dirait que vous avez une sorte d'usine pour les auditeurs, donc la première approche est préférable.

0
Mike 23 sept. 2020 à 21:58