将函数调用转换为Lambda(SAM)

时间:2017-07-19 19:14:47

标签: android kotlin

在android程序中,我有以下代码:

clockCheckBox.setOnClickListener((object: View.OnClickListener {
    override fun onClick(view: View): Unit {
        if (clockCheckBox.isChecked())
            enableClocks()
        else
            disableClocks()
    }
}))

在Android Studio中,出现了一个工具提示,

  

此检查报告实现a的匿名对象文字   java接口,可以转换成单个抽象方法   用lambda表达式调用。

我试过这样做,但我得到的只是语法错误。你能告诉我正确的语法吗?我或许应该解释一下,这段代码在我的活动的onCreate方法中,而clockCheckBox是一个定义为

的局部变量
val clockCheckBox = findViewById(R.id.clockCheckBox) as CheckBox

3 个答案:

答案 0 :(得分:4)

在了解Kotlin的惯例的同时仔细查看检查报告是有用的。

  

此检查报告匿名对象文字实现了一个带有单个抽象方法的 (强调我的)的java接口,可以转换为带有lambda表达式的调用。

本报告中的一个关键是“使用单个抽象方法实现java接口”。这是关键,因为实现这些类型接口的匿名对象可以简洁地编写为lambda。换句话说,您可以跳过匿名对象文字和接口名称,只使用符合单个抽象方法签名的lambda。

对于onClick,等效签名是

    (view: View) -> Unit

所以你的例子的lambda将是

{ view -> if (clockCheckBox.isChecked) enableClocks() else disableClocks() }

但是因为你没有在你的lambda体中使用'view','view - >'可以省略。而不是查看,你使用的是clockCheckBox(在lambda的闭包中是一个View)。

最后,当函数调用的最后一个参数是lambda时,而不是写

myFun( { ... } )

你可以写

myFun { ... }

换句话说,您正在移动括号外的最后一个参数lambda(如果只有一个参数,则可以省略括号)。所以使用lambda的完整示例将是

clockCheckBox.setOnClickListener { 
    if(clockCheckBox.isChecked()) enableClocks() else disableClocks()
}

答案 1 :(得分:2)

上面的代码可以简化如下:

//                v--- parentheses is unnecessary
setOnClickListener {
    //                        v--- boolean property parenthess is unnecessary
    if (clockCheckBox.isChecked)
        enableClocks()
    else
        disableClocks()
}

您可以进一步了解Java Interoperability

答案 2 :(得分:1)

转换它的方法是只保留函数中的接口名称和代码。一张图片(在这种情况下的例子)值得千言万语,这就是它的样子:

clockCheckBox.setOnClickListener(View.OnClickListener {
    if (clockCheckBox.isChecked())
        enableClocks()
    else
        disableClocks()
})

您可以在kotlin docs page上了解更多相关信息。