Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin Android Button.onClickListener causing NoSuchMethodError

I think I've found a quirk of using kotlin for android, or there's some gap in my understanding of the syntax.

Trying to set an onClickListener for a button is throwing a NoSuchMethodError

Here's the code at fault

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's the stacktrace outputted

 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)

Anyone know whats up?

like image 382
Lewiky Avatar asked Jan 18 '26 17:01

Lewiky


1 Answers

Interestingly, I don't get that error, your code compiles for me. However, it won't work for a different reason: you're passing in a lambda as the listener inside the {}, which means that the contents of it will be executed when the click event happens. There is no code to run inside it though, you're just defining a local function named onClick that will never be called.

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 fix your syntax:

First, you can use an object expression to create the listener, this is pretty close to what you wrote, and is along the lines of the classic Java solution, it explicitly creates an anonymous class (note that the OnClickListener interface is actually under the View class):

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 using the previous long form anyway, by making use of SAM conversion:

button.setOnClickListener {
    val intent = ...
}

This solution uses a lambda just like your initial code did, it just doesn't name what interface it converts to explicitly, and drops the () which are not required a single lambda parameter.

like image 178
zsmb13 Avatar answered Jan 21 '26 08:01

zsmb13



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!