Comment fonctionne setOnClickListener en Kotlin : plongeons sous le capot
\n\nChaque développeur Android, en passant de Java à Kotlin, se demande tôt ou tard : « Pourquoi setOnClickListener semble-t-il maintenant si simple et élégant ? » Et ce n'est pas de la magie — derrière cela se cache un mécanisme puissant du langage que nous allons décortiquer aujourd'hui.
\n\nSi vous avez déjà écrit quelque chose comme :
\n\nbutton.setOnClickListener { \n toast("Appuyé !")\n}\n\n\n...alors vous avez déjà utilisé la conversion SAM et les expressions lambda. Mais comment Kotlin transforme-t-il exactement ce code concis en ce qu'Android comprend ? Décortiquons cela.
\n\nL'approche classique en Java : par où tout a commencé
\n\nEn Java, setOnClickListener ressemblait à ceci :
\n\nbutton.setOnClickListener(new View.OnClickListener() {\n @Override\n public void onClick(View v) {\n // votre code\n }\n});\n\n\nIci, nous créions une classe interne anonyme implémentant l'interface View.OnClickListener. Cela fonctionnait, mais le code était lourd. Kotlin a proposé une solution élégante — les expressions lambda.
La transformation Kotlin : à quoi cela ressemble maintenant
\n\nEn Kotlin, le même code peut s'écrire en une seule ligne :
\n\nbutton.setOnClickListener { \n println("Bouton pressé")\n}\n\n\nMais que se passe-t-il sous le capot ? Décomposons cela étape par étape.
\n\nÉtape 1. Conversion SAM
\n\nSAM (Single Abstract Method) — c'est une interface avec une seule méthode abstraite. View.OnClickListener en est un parfait exemple : il n'a qu'une seule méthode onClick(View).
Kotlin convertit automatiquement la lambda en implémentation de cette interface. C'est ce qu'on appelle la conversion SAM. Le compilateur voit que vous passez une lambda là où un View.OnClickListener est attendu, et crée une classe anonyme pour vous.
Autrement dit, lorsque vous écrivez :
\n\nbutton.setOnClickListener { v -> println("Pressé $v") }\n\n\n...Kotlin génère approximativement ce bytecode :
\n\nbutton.setOnClickListener(new OnClickListener() {\n @Override\n public void onClick(View v) {\n System.out.println("Pressé " + v);\n }\n});\n\n\nÉtape 2. Raccourcissement des paramètres
\n\nSi la lambda accepte un seul paramètre, vous pouvez l'omettre et utiliser le nom implicite it :
button.setOnClickListener { \n println("Pressé $it")\n}\n\n\nCela fonctionne car Kotlin sait que le seul paramètre de la méthode onClick est un View. Le compilateur substitue automatiquement it.
Que se passe-t-il au niveau du bytecode ?
\n\nPlongeons encore plus profondément. Lorsque vous utilisez une lambda, Kotlin ne crée pas toujours un nouvel objet. Dans certains cas, il utilise des fonctions inline ou du mise en cache.
\n\nConsidérons deux scénarios :
\n\n- \n
- Lambda sans capture de variables — le compilateur peut créer une instance statique unique et la réutiliser. \n
- Lambda avec capture de variables — un nouvel objet est créé à chaque appel, car l'état doit être conservé. \n
Exemple avec capture :
\n\nvar counter = 0\nbutton.setOnClickListener {\n counter++\n println("Pressions : $counter")\n}\n\n\nIci, Kotlin crée un objet qui stocke une référence à counter. C'est un peu plus coûteux, mais dans la plupart des cas, cela reste imperceptible.
Alternatives à setOnClickListener en Kotlin
\n\nBien que les lambdas soient la méthode la plus populaire, il existe d'autres approches. Examinons-les.
\n\n1. Référence de méthode
\n\nSi vous avez déjà une fonction dont la signature correspond, vous pouvez passer une référence à celle-ci :
\n\nfun handleClick(view: View) {\n println("Gestionnaire : $view")\n}\n\nbutton.setOnClickListener(::han