Android 使用lambda的Kotlin setOnClickListener语法

Android 使用lambda的Kotlin setOnClickListener语法,android,kotlin,lambda,Android,Kotlin,Lambda,在Kotlin中设置单击侦听器时,我们可以编写: rollButton.setOnClickListener( 对象:View.OnClickListener{ 覆盖有趣的onClick(v:视图?){ 滚动骰子(); } } ) SAM转换后,我们可以写: rollButton.setOnClickListener({v->rollDice()}) 但我注意到kotlin也接受: rollButton.setOnClickListener(View.OnClickListener(){v-

在Kotlin中设置单击侦听器时,我们可以编写:

rollButton.setOnClickListener(
对象:View.OnClickListener{
覆盖有趣的onClick(v:视图?){
滚动骰子();
}
}
)
SAM转换后,我们可以写:

rollButton.setOnClickListener({v->rollDice()})
但我注意到kotlin也接受:

rollButton.setOnClickListener(View.OnClickListener(){v->rollDice()})
以及

rollButton.setOnClickListener(View.OnClickListener{v->rollDice()})
我想知道这里发生了什么?我的意思是
setOnClickListener
应该使用匿名类或SAM速记之类的东西来实现
OnClickListener
。这是某种中间阶段还是什么


非常感谢对参考资料的任何解释或链接。

对于这些示例,让界面为:

fun interface IntUser {
    fun use(value: Int)
}
SAM转换使您可以像使用lambda作为参数的构造函数一样使用接口的名称

val x = IntUser({ println(it) })
允许您将lambda移到括号外,如第二个示例所示:

val y = IntUser() { println(it) }
val z = IntUser { println(it) }
当lambda是唯一的参数时使用尾部lambda语法时,可以省略括号,如第三个示例中所示:

val y = IntUser() { println(it) }
val z = IntUser { println(it) }
最后,SAM转换可以做的另一件事是让您传递一个裸lambda来代替接口参数。它可以从函数参数推断类型:

rollButton.setOnClickListener {
    rollDice()
}

在这里,我们使用lambda作为唯一参数,因此我们也使用尾随lambda语法并省略空括号。

对于这些示例,让接口为:

fun interface IntUser {
    fun use(value: Int)
}
SAM转换使您可以像使用lambda作为参数的构造函数一样使用接口的名称

val x = IntUser({ println(it) })
允许您将lambda移到括号外,如第二个示例所示:

val y = IntUser() { println(it) }
val z = IntUser { println(it) }
当lambda是唯一的参数时使用尾部lambda语法时,可以省略括号,如第三个示例中所示:

val y = IntUser() { println(it) }
val z = IntUser { println(it) }
最后,SAM转换可以做的另一件事是让您传递一个裸lambda来代替接口参数。它可以从函数参数推断类型:

rollButton.setOnClickListener {
    rollDice()
}

在这里,我们使用lambda作为唯一参数,因此我们也使用后面的lambda语法并省略空括号。

“Kotlin可以将签名与接口的单个方法的签名匹配的任何lambda表达式转换为实现接口的类的实例”()和“If[a]lambda是[a function]的唯一参数,括号可以省略“()。因此,为什么您可以编写类似于
rollButton.setOnClickListener({v->rollDice()})
甚至
rollButton.setOnClickListener{v->rollDice()}
的东西,既然我理解了SAM转换的实际含义,那么
rollButton.setOnClickListener是什么呢({v->rollDice()})
正在工作?接口的名称丢失!编译器知道
setOnClickListener
需要一个
OnClickListener
“Kotlin可以将签名与接口的单个方法的签名匹配的任何lambda表达式转换为实现接口的类的实例”()和“如果[a] lambda是[a function]的唯一参数,括号可以省略“()。因此,您可以编写
rollButton.setOnClickListener({v->rollDice()})
甚至
rollButton.setOnClickListener{v->rollDice()}
现在我了解了SAM转换实际上是什么,那么
rollButton.setOnClickListener({v->rollDice()})是怎样的呢
正在工作?接口的名称丢失!编译器知道
setOnClickListener
需要一个
OnClickListener
。很好的解释,可能只是没有说明这只适用于函数接口。@m0skit0、SAM或单一抽象方法接口也被称为函数接口,不是吗?这是真的对于Java接口,但对于Kotlin接口,您还必须将
fun
放在
interface
之前,才能将其视为功能接口并允许lambda转换。是的,我的意思是,与其说“让您传递一个裸lambda来代替接口参数”,不如说它更正确“让您传递一个裸lambda来代替函数接口参数",等等。我回答了OP。很好的解释,可能只是遗漏了这只适用于函数接口。@m0skit0,SAM或单一抽象方法接口也被称为函数接口,不是吗?对于Java接口是这样的,但是对于Kotlin接口,您还必须在
接口之前添加
fun
ode>将其视为功能接口并允许lambda转换。是的,我的意思是,与其说“让你传递一个裸lambda来代替接口参数”,不如说“让你传递一个裸lambda来代替功能接口参数”,等等。我是在回应OP。