8

从 Kotlin 调用 Java 代码时,会有SAM 转换,因此 Java 代码如下所示:

adapter.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view, int position) {
        // Do stuff here
    }
});

可以是这样的:

adapter.setOnClickListener { view, position ->
    // Do stuff
}

现在,我正在开发一个 Kotlin 项目,我想将功能接口定义为事件侦听器:

interface OnSomeActionListener {

    fun onSomeAction(parameter1: Int, parameter2: String)

}

SomeClass我有一个设置监听器的函数:

    ...

    private var onSomeActionListener: OnSomeActionListener? = null

    fun setOnSomeActionListener(listener: OnSomeActionListener) {
        onSomeActionListener = listener
    }

    ...

当我创建这个类的一个实例并尝试调用 setter 函数时,我会这样做:

val thing = SomeClass()

thing.setOnSomeActionListener(object : OnSomeActionListener {
    override fun onSomeAction(parameter1: Int, parameter2: String) {
        // Do stuff here
    }
})

我知道 Kotlin 具有函数类型,因此不支持来自各种站点的 SAM 转换,例如这个

我已经阅读了一些关于函数类型的内容,但我之前没有使用过它们。

我将如何重写我的代码,以便我可以像这样调用 setter 函数?

val thing = SomeClass()

thing.setOnSomeActionListener { parameter1, parameter2 ->
    // Do stuff here
}

.

4

3 回答 3

15

函数类型如下所示:

(Parameters) -> ReturnType

在您的情况下,您可以使用(View, Int) -> Unit. 它看起来像这样:

private var onSomeActionListener: ((View, Int) -> Unit)? = null

fun setOnSomeActionListener(listener: (View, Int) -> Unit) {
    onSomeActionListener = listener
}

private fun callSomeActionListener(view: View, position: Int) {
    onSomeActionListener?.invoke(view, position)
}

添加名称

在功能类型中,您还可以指定参数的名称。这在后台并没有太大变化,但他们可以在此处和调用代码中增加一些清晰度,这很好。

(view: View, position: Int) -> Unit

使用类型别名

为了避免(View, Int) -> Unit每次都输入,你可以定义一个 typealias:

typealias OnSomeActionListener = (view: View, position: Int) -> Unit

这样您的代码现在再次看起来像这样:

private var onSomeActionListener: OnSomeActionListener? = null

fun setOnSomeActionListener(listener: OnSomeActionListener?) {
    onSomeActionListener = listener
}   

并称之为:

val thing = SomeClass()

thing.setOnSomeActionListener { view, position ->
    // Do stuff here
}
于 2017-07-12T09:35:04.407 回答
0

嗯,是这样的:

// declare a variable of nullable function type:
var onSomeActionListener: ((Int, String) -> Unit)? = null

// declare higher-order function:
fun setOnSomeActionListener(listener: (Int, String) -> Unit) {
    onSomeActionListener = listener
}

// set listener:
val listener: (Int, String) -> Unit = { p1, p2 -> { /* some stuff */ } }
setOnSomeActionListener(listener)

// or in one line:
setOnSomeActionListener { p1, p2 -> { /* some stuff */ } }

更多信息:高阶函数和 Lambda

于 2017-07-12T09:02:25.897 回答
0

如何定义接受函数并返回接口的函数?

fun makeOnSomeActionListener(f: (Int,String) -> Unit) = object : OnSomeActionListener {
    override fun onSomeAction(parameter1: Int, parameter2: String) = f(parameter1, parameter2)
}

该接口将其工作委托给f.

然后你可以写

val thing = SomeClass()

thing.setOnSomeActionListener(makeOnSomeActionLisener { parameter1, parameter2 ->
  // Do stuff here
})
于 2017-07-12T13:47:09.073 回答