【问题标题】:Setting anonymous interface in Kotlin [duplicate]在 Kotlin 中设置匿名接口
【发布时间】:2018-06-19 06:12:29
【问题描述】:

我的Adapter 类中有一个接口:

interface OnItemClickListener {
    fun onItemClick(view: View)
}

请注意我的 interface 在 Kotlin 中。

我想通过这个方法设置:

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

如何像在 Java 中那样使用 Fragment 类中的 setItemClickListener 方法?即

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

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

【问题讨论】:

    标签: java android lambda kotlin adapter


    【解决方案1】:

    没有 lambda 你也可以这样做

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

    【讨论】:

    • 到目前为止,这是唯一对我有用的答案。但我真的很想了解更多关于 lambdas 的知识。
    【解决方案2】:

    问题是你的接口是在 Kotlin 中定义的(因为它有fun)。 Lambdas can only be used for Java interfaces:

    还请注意,此功能仅适用于 Java 互操作;由于 Kotlin 具有适当的函数类型,因此不需要将函数自动转换为 Kotlin 接口的实现,因此不受支持。

    所以在 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 -> ... })
    

    【讨论】:

    • 这为我清除了一切。谢谢你。但是,如何使用OnItemClickListener 内联工厂方法?
    • 编辑显示使用。
    • 抱歉,如何在适配器的onBindViewHolder 方法中调用onItemClick
    • 你了解如何访问监听器吗?然后像往常一样调用它的方法。
    • 抱歉,我刚接触 Kotlin。你能给我一个代码截图吗? @Alexey Romanov
    【解决方案3】:

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

    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)
    }
    

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

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

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

    【讨论】:

    • 我尝试了第一个和第二个解决方案,但它不起作用。它说Required: Adapter. OnItemClickListener Found: () -> Unit
    【解决方案4】:

    这就是我们在 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

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

    【讨论】:

    • 您好,您的代码似乎无法编译。说Type mismatch Required UpdatesAdapter.OnItemClickListener Found: () -> Int)
    • 你的UpdatesAdapter.OnItemClickListener只有一种方法吗?
    • @Cililing 是的。是fun onItemClick(view: View)
    猜你喜欢
    • 1970-01-01
    • 2016-10-06
    • 2020-05-22
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    相关资源
    最近更新 更多