3 votes

Kotlin Android Button.onClickListener provoquant NoSuchMethodError

Je pense avoir trouvé une particularité de l'utilisation de Kotlin pour Android, ou il y a un vide dans ma compréhension de la syntaxe.

Essayer de définir un onClickListener pour un bouton lance une NoSuchMethodError

Voici le code en faute

button.setOnClickListener(Button.OnClickListener {
            fun onClick(view: View){
                val intent : Intent = Intent(this,DetailActivity::class.java)
                if(obj is String) {
                    intent.putExtra("Sujet", obj)
                }
                startActivity(intent)
            }
        })

Et voici la pile d'exécution affichée

java.lang.NoSuchMethodError: No static method OnClickListener(Lkotlin/jvm/functions/Function1;)Landroid/view/View$OnClickListener; in class Landroid/widget/Button; or its super classes (déclaration de 'android.widget.Button' apparaît dans /system/framework/framework.jar:classes2.dex)

Quelqu'un sait ce qui se passe?

6voto

zsmb13 Points 36441

Intéressant, je n'ai pas cette erreur, votre code compile pour moi. Cependant, il ne fonctionnera pas pour une autre raison : vous passez une lambda en tant qu'auditeur à l'intérieur des {}, ce qui signifie que son contenu sera exécuté lorsque l'événement de clic se produira. Il n'y a cependant aucun code à exécuter à l'intérieur, vous définissez simplement une fonction locale nommée onClick qui ne sera jamais appelée.

button.setOnClickListener(Button.OnClickListener {
    fun onClick(view: View){
        ...
    }

    Log.d("TAG", "hi") // this is the code that would be executed on click events
})

Il y a deux façons de corriger votre syntaxe :

Tout d'abord, vous pouvez utiliser une object expression pour créer l'écouteur, cela ressemble beaucoup à ce que vous avez écrit et est dans la lignée de la solution classique en Java, elle crée explicitement une classe anonyme (notez que l'interface OnClickListener est en fait sous la classe View):

button.setOnClickListener(object: View.OnClickListener {
    override fun onClick(v: View?) {
        val intent = ...
    }
})

Ou vous pouvez utiliser la syntaxe plus courte et plus proche de Kotlin que l'IDE suggérera lorsque vous essayez d'utiliser la forme longue précédente de toute façon, en utilisant la conversion SAM :

button.setOnClickListener {
    val intent = ...
}

Cette solution utilise une lambda tout comme votre code initial, elle ne nomme simplement pas explicitement l'interface vers laquelle elle est convertie, et supprime les () qui ne sont pas nécessaires pour un seul paramètre lambda.

1voto

bjornson Points 632

Essayer

button.setOnClickListener {
    // Code du gestionnaire ici
}

0voto

Vous pouvez essayer :

// cas 1
button?.setOnClickListener { view -> 
   // gestionnaire ici
}

// cas 2
button?.setOnClickListener {
   // vous pouvez utiliser le mot-clé 'it' pour utiliser la vue membre
   // gestionnaire ici
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X