Kotlin Android Button.onClickListener raises NoSuchMethodError
I think I found a quirk of using kotlin for android, or there is some gap in my understanding of the syntax.
Trying to set onClickListener
for a button is to do thisNoSuchMethodError
Here's the error code
button.setOnClickListener(Button.OnClickListener {
fun onClick(view: View){
val intent : Intent = Intent(this,DetailActivity::class.java)
if(obj is String) {
intent.putExtra("Topic", obj)
}
startActivity(intent)
}
})
And here is the stop trace taken out
java.lang.NoSuchMethodError: No static method OnClickListener(Lkotlin/jvm/functions/Function1;)Landroid/view/View$OnClickListener; in class Landroid/widget/Button; or its super classes (declaration of 'android.widget.Button' appears in /system/framework/framework.jar:classes2.dex)
Does anyone know what?
source to share
Interestingly, I am not getting this error, your code compiles for me. However, this won't work for another reason: you are passing the lambda as a listener internally {}
, which means that its content will be executed when the click event occurs. There is no code inside this code, but you just define a named local function that will never be called.onClick
button.setOnClickListener(Button.OnClickListener {
fun onClick(view: View){
...
}
Log.d("TAG", "hi") // this is the code that would be executed on click events
})
There are two ways to correct your syntax:
First, you can use an expression object
to create a listener, this is pretty close to what you wrote and goes the lines of a classic Java solution, it explicitly creates an anonymous class (note that the interface is OnClickListener
actually in the class View
):
button.setOnClickListener(object: View.OnClickListener {
override fun onClick(v: View?) {
val intent = ...
}
})
Or, you can use the shorter, more Kotlin-like syntax that the IDE will suggest when you try to use the previous long form anyway using SAM Transform :
button.setOnClickListener {
val intent = ...
}
This solution uses a lambda in the same way as your original code, but it just doesn't specify which interface it will explicitly convert, and discards ()
which doesn't require a single lambda parameter.
source to share