使用 lambda 的 Kotlin setOnClickListener 语法

Md *_*din 3 lambda android kotlin

在 Kotlin 中设置点击监听器时,我们可以这样写:

rollButton.setOnClickListener(
    object: View.OnClickListener {
        override fun onClick(v: View?) {
            rollDice();
        }
    }
)
Run Code Online (Sandbox Code Playgroud)

SAM转换后,我们可以写:

rollButton.setOnClickListener({ v -> rollDice() })
Run Code Online (Sandbox Code Playgroud)

但我注意到 kotlin 也接受:

rollButton.setOnClickListener(View.OnClickListener() { v -> rollDice() })
Run Code Online (Sandbox Code Playgroud)

rollButton.setOnClickListener(View.OnClickListener { v -> rollDice() })
Run Code Online (Sandbox Code Playgroud)

我想知道这里发生了什么?我的意思是应该使用匿名类或 SAM 速记法setOnClickListener来实现。OnClickListener这是某种中间阶段还是什么?

任何解释或资源链接都将受到高度赞赏。

Ten*_*r04 5

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

fun interface IntUser {
    fun use(value: Int)
}
Run Code Online (Sandbox Code Playgroud)

SAM 转换允许您像使用 lambda 作为参数的构造函数一样使用接口名称。

val x = IntUser({ println(it) })
Run Code Online (Sandbox Code Playgroud)

尾随 lambda 语法允许您将 lambda 移到括号之外,就像第二个示例一样:

val y = IntUser() { println(it) }
Run Code Online (Sandbox Code Playgroud)

当 lambda 是唯一参数时使用尾随 lambda 语法时,您可以省略括号,如第三个示例中所示:

val z = IntUser { println(it) }
Run Code Online (Sandbox Code Playgroud)

最后,SAM 转换可以做的另一件事是让您传递一个裸 lambda 来代替接口参数。它可以从函数参数推断类型:

rollButton.setOnClickListener {
    rollDice()
}
Run Code Online (Sandbox Code Playgroud)

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