我想我发现使用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)
}
})
这是输出的stacktrace
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)
有人知道发生了什么吗?
最佳答案
有趣的是,我没有得到该错误,您的代码为我编译。但是,它由于不同的原因而无法工作:您将λ作为传递者传递给{}
内的侦听器,这意味着将在click事件发生时执行其内容。尽管其中没有代码可运行,但是您只是在定义一个永远不会被调用的名为onClick
的local function。
button.setOnClickListener(Button.OnClickListener {
fun onClick(view: View){
...
}
Log.d("TAG", "hi") // this is the code that would be executed on click events
})
有两种方法可以修复语法:
首先,您可以使用
object
expression创建侦听器,这与您编写的内容非常接近,并且与经典Java解决方案类似,它显式创建了一个匿名类(请注意OnClickListener
接口(interface)实际上在View
类之下):button.setOnClickListener(object: View.OnClickListener {
override fun onClick(v: View?) {
val intent = ...
}
})
或者,您可以使用SAM conversion来使用更短,更类似于Kotlin的语法,当您尝试使用以前的长格式时,IDE会建议该语法:
button.setOnClickListener {
val intent = ...
}
此解决方案使用lambda就像您的初始代码一样,只是没有明确命名要转换为哪个接口(interface),而是删除了不需要单个lambda参数的
()
。