Kotlin中view.setOnLongClickListener和view.onClick的比较

时间:2018-07-10 10:52:05

标签: android kotlin android-context

我正在尝试从回收者视图适配器中调用另一个函数,我在holder.itemView中添加了onclick侦听器。我在“活动”中尝试使用setOnClickListener作为onClick参数的this@MainActivitycontext,效果很好。

btn.setOnClickListener { showDialog(this@MainActivity) }
btn.onClick { showDialog(this@MainActivity) }

但是onClick在适配器中不起作用,因为

holder.itemView.setOnClickListener {
    showDialog(context, notes[position])
} // This works fine

// Type mismatch required Context, Found CoroutineContext
holder.itemView.onClick { showDialog(context, notes[position]) }

如果我想使用onClick而不是setOnClickListener

,该怎么办?

1 个答案:

答案 0 :(得分:2)

也许尝试一下:

class NotesAdapter(private val ctx: Context) : RecyclerView.Adapter<NotesAdapter.NotesViewHolder>() {
    // Etc
    holder.itemView.onClick { showDialog(ctx, notes[position]) }
}

编辑-解释

无论如何,我都不是Kotlin的专家,但是您所得到的错误是一个非常清楚的线索,表明发生了什么。

在幕后调用holder.itemView.onClick时,您正在调用itemView.setOnClickListener,它采用View.OnClickListener的实例。因此,您可以做这样的事情,并且可能效果很好:

class NotesAdapter(private val context: Context) : RecyclerView.Adapter<NotesAdapter.NotesViewHolder>() {
    // Etc
    holder.itemView.onClick(View.OnClickListener(){
        void onClick(v: View) {
            showDialog(context, notes[position])
        }
    })
}

相反,您想使用Kotlins的一些干净语法并将其传递给lambda。这是完全有效的,而且更清洁。但是,似乎lambda(或coroutine)显然也有一个名为context的字段,并且它具有一种CoroutineContext。在上面的示例中继续进行以下操作:

holder.itemView.onClick(View.OnClickListener(){
    var context: CoroutineContext
    void onClick(v: View) {
        showDialog(context, notes[position])
    }
})

在这种情况下,当您调用showDialog时,会得到当前作用域的“上下文”,它是错误的类型,这就是为什么会出现“类型不匹配”错误的原因。

在Java中,还有另一种解决方案,我只是不知道等效的Kotlin语法。您将执行以下操作:

holder.itemView.onClick { showDialog(NotesAdapter.this.context, notes[position]) }

这只是告诉编译器您要查找的上下文在NotesAdapter范围内而不在Coroutine范围内的另一种方式