使用lambdas创建我自己的监听器

时间:2018-04-06 08:42:26

标签: android kotlin

我想在我的活动/片段中存档

 adapter.setOnItemClickListener { item ->
          //do smt with item
        }

我在适配器中设置但没有运气:

private var listener: OnItemClickListener?=null  

override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
     val item = getItem(position)
     item?.let { holder.bindView(it) }
     holder.itemView.setOnClickListener { item?.let { listener?.onItemClick(it) } }
     }

fun setOnItemClickListener(listener: (Item) -> Unit){
    this.listener = listener as OnItemClickListener //this will throw type cast error
    }

编辑1:我应该使用两种类型来完成同样的工作吗?

private var lambdaListener: ((Item) -> Unit)? = null

private var listener: OnItemClickListener?=null  

override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        val item = getItem(position)
        item?.let { holder.bindView(it) }
        holder.itemView.setOnClickListener {
            item?.let { listener?.onItemClick(it) }
            item?.let { it1 -> lambdaListener?.invoke(it1) }
        }
    }

fun setOnItemClickListener(listener: (Item) -> Unit) {
        lambdaListener = listener
}

android-kotlin-extensions如何创建lambda表达式,如:view.setOnClickListener{view -> //do smt } 甚至

view.setOnClickListener{//do smt }

编辑决赛: 感谢标记正确的答案,它并没有真正解决问题,但给了我这个想法:

this.listener = object : OnItemClickListener {
        override fun onItemClick(item: Item) = listener(item)
    }

用OnItemClickListener仍然是一个kotlin接口,无需将其重写为java接口

2 个答案:

答案 0 :(得分:4)

  

android-kotlin-extensions如何创建lambda表达式,如:view.setOnClickListener{view -> //do smt }甚至view.setOnClickListener{//do smt }

Kotlin有SAM Conversionsview.setOnClickListener{//do smt }有效,因为单参数方法有一个默认名称it

  

这意味着只要接口方法的参数类型与Kotlin函数的参数类型匹配,Kotlin函数文字就可以使用单个非默认方法自动转换为Java接口的实现。

当前仅Java接口支持SAM转换。有关进一步的讨论,请参阅here

要解决这个问题,一种方法是自己包装lambda。

fun setOnItemClickListener(listener: (Item) -> Unit) {
    listener = OnItemClickListener { listener.invoke(it) }
}

答案 1 :(得分:1)

您的lambda不适合强制转换为OnItemClickListener界面。您必须手动实现接口并在那里调用该函数。要改进实施,您还可以使用inline功能。

inline fun setOnItemClickListener(crossinline listener: (Item) -> Unit) {
    this.listener = OnItemClickListener { listener(it) }
}

如果OnItemClickListener Java 接口,这将有效。如果它是 Kotlin 接口,则必须使用object表示法实现它。

inline fun setOnItemClickListener(crossinline listener: (Item) -> Unit) {
    this.listener = object : OnItemClickListener {
        override fun onItemClick(item: Item) = listener(item)
    }
}