在 Kotlin 中设置匿名接口

Setting anonymous interface in Kotlin

我的 Adapter class:

中有一个接口
interface OnItemClickListener {
    fun onItemClick(view: View)
}

请注意,我的 interface 使用 Kotlin。

我想通过这个方法设置:

public fun setItemClickListener(itemClickListener: OnItemClickListener) {
    this.onItemClickListener = itemClickListener
}

如何在 Fragment class 中使用 setItemClickListener 方法,就像我在 Java 中所做的那样?即

adapter.setItemClickListener(new OnItemClickListener() {
   @Override
   public void onItemClick(View view) {
    // do something
   }
}

我知道我可以使用 onItemTouchListener,但我对 Kotlin 还是个新手,我正在尝试学习一些技术,例如 Lambdas 等。

这就是我们在 lambda 中的做法

adapter.setItemClickListener{ Log.i("Adapter", "onItemClick event fired on " + it.id) }

这里itView的实例,是onItemClick方法的参数

有关 it 的更多信息在此处 https://kotlinlang.org/docs/reference/lambdas.html#it-implicit-name-of-a-single-parameter

您可以在此处的 Kotlin 文档中找到更多信息 https://kotlinlang.org/docs/reference/lambdas.html#lambda-expressions-and-anonymous-functions

如果没有 lambda,你可以这样做

adapter.setItemClickListener(object :View.OnItemClickListener{
            override fun onItemClick(p0: View?) {

            }
        })

如果你想用单一方法分配接口,你可以这样写:

adapter.setItemClickListener { view ->
    /* some code here */
}

甚至更好:

adapter.setItemClickListener { 
    /* some code here, to use "view" use keyword "it" */
}

如果您想更深入地了解,让我们分析一下您的方法的签名:

public fun setItemClickListener(itemClickListener: OnItemClickListener)

这实际上等于

public fun setItemClickListener(singleMethodListener: (View) -> Unit)

如果你的最后一个参数是函数,你可以忘记'()',并传递lambda。 再举一个例子:

public fun setItemClickListener(parameter: Int, singleMethodListener: (View) -> Unit)

要调用上面的方法,您的代码应该是:

item.setItemClickListener(0) { /* lambda here */ }

问题是当你有不止一种方法的接口时,因为那样你就不能传递 lambda :(

示例:

interface OnItemClickListener {
     fun onItemClick(view: View)
     fun onDoubleItemClick(view: View)
}

那么,你不能通过sample labda,因为你必须定义2个方法。然后,你必须像 java 一样做同样的事情,但在其他语法中:

adapter.setItemClickListener(object : OnItemClickListener {
    /* method declarations here, like in java */
})

我希望我已经解释了 Kotlin 中的 base-lambda 语法 :D 有任何问题吗?问 ;)

问题是您的界面是在 Kotlin 中定义的(因为它具有 fun)。 Lambdas can only be used for Java interfaces:

Also note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.

所以在 Kotlin 中你应该使用

public fun setItemClickListener(itemClickListener: (View) -> Unit)

而不是定义 OnItemClickListener。您还可以创建一个工厂方法:

// in Adapter's companion object
public inline fun OnItemClickListener(body: (View) -> Unit) = object : OnItemClickListener {
    override fun onItemClick(view: View) { body(view) }
}

然后

adapter.setItemClickListener(Adapter.OnItemClickListener { view -> ... })