Kotlin Android Button.onClickListener导致NoSuchMethodError

我想我已经找到了一个使用kotlin for android的怪癖,或者在我对语法的理解上存在一些空白。

试图为一个按钮设置一个onClickListener是抛出一个NoSuchMethodError

这是错误的代码

 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) } }) 

这里是输出的堆栈跟踪

  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) 

任何人都知道吗?

有趣的是,我没有得到这个错误,你的代码为我编译。 但是,它不会工作的原因不同:你传递一个lambda作为{}的侦听器,这意味着它的内容将在click事件发生时被执行。 没有代码在里面运行,你只是定义一个名为onClick的本地函数 ,永远不会被调用。

 button.setOnClickListener(Button.OnClickListener { fun onClick(view: View){ ... } Log.d("TAG", "hi") // this is the code that would be executed on click events }) 

有两种方法可以修复你的语法:

首先,您可以使用一个object表达式来创建侦听器,这与您所写的非常接近,并且沿着经典的Java解决方案的路线,它显式地创建了一个匿名类(请注意, OnClickListener接口实际上是在View类):

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

或者,您可以使用更短,更类似Kotlin的语法,当您尝试使用以前的长格式时,IDE会建议您使用SAM转换 :

 button.setOnClickListener { val intent = ... } 

这个解决方案就像你的初始代码一样使用一个lambda表达式,它只是没有明确指定它转换的接口的名称,而是抛弃了不需要单个lambda参数的()

尝试

 button.setOnClickListener { // Handler code here }