【问题标题】:Android - Kotlin - object must be declared abstract or implement abstract memberAndroid - Kotlin - 对象必须声明为抽象或实现抽象成员
【发布时间】:2017-05-25 20:29:49
【问题描述】:

我已经为我的 RecyclerView 设置了一个 ItemClickLister,如下所示:

ItemClickSupport.addTo(recyclerView!!).setOnItemClickListener(
                    object : ItemClickSupport.OnItemClickListener {
                        override fun onItemClicked(recyclerView: RecyclerView?, position: Int, v: View?) {
                            val row = recyclerView!!.getChildAt(position)
                            val el = row.findViewById(R.id.active_expandablelayout) as ExpandableLayout

                            if (el.isExpanded) {
                                el.collapse()
                            } else {
                                el.expand()
                            }
                        }
                    }
            )

使用我翻译成 Kotlin 的 ItemClickSupport 库。

我在object(第 2 行)收到一条错误消息:

对象必须声明为抽象或实现抽象成员。

我真的是 Kotlin 的新手,在 SO 上也找不到任何解决方案。

非常感谢任何帮助。

编辑:

这是我的ItemClickSupport.kt

class ItemClickSupport private constructor(private val mRecyclerView: RecyclerView) {
    private var mOnItemClickListener: OnItemClickListener? = null
    private var mOnItemLongClickListener: OnItemLongClickListener? = null
    private val mOnClickListener = View.OnClickListener { v ->
        if (mOnItemClickListener != null) {
            val holder = mRecyclerView.getChildViewHolder(v)
            mOnItemClickListener!!.onItemClicked(mRecyclerView, holder.adapterPosition, v)
        }
    }
    private val mOnLongClickListener = View.OnLongClickListener { v ->
        if (mOnItemLongClickListener != null) {
            val holder = mRecyclerView.getChildViewHolder(v)
            return@OnLongClickListener mOnItemLongClickListener!!.onItemLongClicked(mRecyclerView, holder.adapterPosition, v)
        }
        false
    }
    private val mAttachListener = object : RecyclerView.OnChildAttachStateChangeListener {
        override fun onChildViewAttachedToWindow(view: View) {
            if (mOnItemClickListener != null) {
                view.setOnClickListener(mOnClickListener)
            }
            if (mOnItemLongClickListener != null) {
                view.setOnLongClickListener(mOnLongClickListener)
            }
        }

        override fun onChildViewDetachedFromWindow(view: View) {

        }
    }

    init {
        mRecyclerView.setTag(R.id.item_click_support, this)
        mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener)
    }

    fun setOnItemClickListener(listener: OnItemClickListener): ItemClickSupport {
        mOnItemClickListener = listener
        return this
    }

    fun setOnItemLongClickListener(listener: OnItemLongClickListener): ItemClickSupport {
        mOnItemLongClickListener = listener
        return this
    }

    private fun detach(view: RecyclerView) {
        view.removeOnChildAttachStateChangeListener(mAttachListener)
        view.setTag(R.id.item_click_support, null)
    }

    interface OnItemClickListener {

        fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View)
    }

    interface OnItemLongClickListener {

        fun onItemLongClicked(recyclerView: RecyclerView, position: Int, v: View): Boolean
    }

    companion object {

        fun addTo(view: RecyclerView): ItemClickSupport {
            var support: ItemClickSupport? = view.getTag(R.id.item_click_support) as ItemClickSupport
            if (support == null) {
                support = ItemClickSupport(view)
            }
            return support
        }

        fun removeFrom(view: RecyclerView): ItemClickSupport {
            val support = view.getTag(R.id.item_click_support) as ItemClickSupport
            support?.detach(view)
            return support
        }
    }
}

这是一个包含整个错误及其发生位置的屏幕截图:

【问题讨论】:

  • 您遗漏了以下信息:1)OnItemClickedListener的接口定义,分享一下,我们不要猜测,它应该在问题中。 2)您遗漏了完整的错误消息,它抱怨的成员名称未实现(以防万一您在该界面中做了一些我们看不到的事情)。 3) 如果您按照以下答案之一的建议使用 lambda 版本,它会告诉您发生了什么,但如果没有原始界面,我们无法告诉您如何解释。
  • @JaysonMinard 请查看更新后的问题
  • 谢谢,现在我们有了回答问题所需的信息。该实现的 Java 版本将不同于用 Kotlin 编写的相同内容,因为 Kotlin 更具体地与 Kotlin 代码交谈,而在与 Java 代码交谈时则更宽松一些。

标签: android android-recyclerview kotlin


【解决方案1】:

您的接口和方法签名不匹配。您的界面将一个函数声明为:

fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View)

然后您将其覆盖为:

fun onItemClicked(recyclerView: RecyclerView?, position: Int, v: View?)

这些不是相同的方法签名。

如果这是一个 Java 接口,您可以在更改可空性时覆盖,因为不清楚可空性是什么(在 Java 代码中没有注释)。但由于您将其移植到 Kotlin 界面,您必须使用相同的确切签名覆盖。相反,您将 RecyclerView?View? 都设为可空,这会导致与原始签名不匹配。将您的覆盖函数更改为:

override fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View)

由于这是一个 Kotin 接口,因此您不能使用 SAM 转换为 Lambda,这就是为什么之前提供的其他答案不起作用的原因。如果这是一个 Java 接口,您可以这样做。您可以在KT-7770 中跟踪 Kotlin 接口的 SAM 转换。

如果您希望这段代码更符合 Kotlin 的习惯,您可能需要函数引用或 lambda,而不是接口,并且您应该这样做,而不是依赖 SAM 转换。您可以在Higher-Order Functions and Lambdas 中阅读更多相关信息。这超出了您的问题范围,无法详细说明。

【讨论】:

  • 很好的答案解决了我的问题。也感谢关于 kotlin 的建议,我正在努力学习,因为它使用起来非常快速和方便。
【解决方案2】:

试试看:

ItemClickSupport.addTo(listView).setOnItemClickListener(object : ItemClickSupport.OnItemClickListener{
        override fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View) {
            val row = recyclerView!!.getChildAt(position)
            val el = row.findViewById(R.id.active_expandablelayout) as ExpandableLayout

            if (el.isExpanded) {
                el.collapse()
            } else {
                el.expand()
            }
        }

    })

【讨论】:

  • 我做到了,这样做我得到了预期的 ItemClickSupport.OnItemClickListener 类型不匹配,发现 (???, ???, ???) -> Unit。如果我明确我得到的参数类型(RecyclerView,Int,View)-> Unit,但显然错误仍然存​​在
  • 你确定你使用正确import
  • 我导入了 ItemClickSupport 类
  • 您在使用 ItemClickSupport 库吗?您是否使用 Android Studio 内置命令在 Kotlin 中翻译了它?
  • 我将你的代码复制到我的项目中,它工作正常。检查导入、清理、构建
猜你喜欢
  • 2017-08-17
  • 1970-01-01
  • 2015-02-28
  • 1970-01-01
  • 2015-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多