0

I was trying to convert my app from Java to Kotlin.

I used the Android Studio Built-in converter and fixed most of the errors it generated.

Being new to Kotlin this one is giving me a really hard time:

I got this class which was written in Java and got converted, apparently without any error, which helps me managing item clicks in a RecyclerView:

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

In the main activity, after conversion it's set like this in the onCreate function:

ItemClickSupport.addTo(recyclerView!!).setOnItemClickListener { recyclerView, position, v ->
            val itemIntent = Intent(this@AddSubscription, CreateSubscription::class.java)

            ...
        }

The IDE is giving me the following error:

Type mismatch:

required: ItemClickSupport.OnItemClickListener

Found: (???, ???, ???) -> Unit

Now, I know Unit is Kotlin's void, but I can't figure out where the error is.

After checking this answer as suggested, I wrote the following code:

ItemClickSupport.addTo(recyclerView!!).setOnItemClickListener(
                object: ItemClickSupport.OnItemClickListener {
                    val itemIntent = Intent(this@AddSubscription, CreateSubscription::class.java)
                    val bundle = Bundle()
                    bundle.putParcelable("selected", filteredList!![position])
                    itemIntent.putExtras(bundle)
                    startActivity(itemIntent)
        })

Now I'm getting an

expected member declaration

which as stated in this other answer it has to do with the constructor.

Is this the ItemClickSupport.OnItemClickListener constructor? If so, what should I change?

I suspect the error is still caused by the OnClickSupport class being poorly converted into kotlin even if it does not have any sintax errors

Daniele
  • 4,163
  • 7
  • 44
  • 95

1 Answers1

2

Since you've converted both files to Kotlin and as the OnItemClickListener interface is written in Kotlin, you can't pass a function lambda like that. Best way is to create an anonymous instance of the interface (you can also use lambda for that, but I'm posting without lambda for sake of understanding)

ItemClickSupport.addTo(recyclerView!!)
    .setOnItemClickListener (object:OnItemClickListener{
        override fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View ){ 
            val itemIntent = Intent(this@AddSubscription, CreateSubscription::class.java)
             ... 
        }
    })

Alternatively, you can use HighOrder Function inside ItemClickSupport to receive lambda only and avoid interface.

Daniele
  • 4,163
  • 7
  • 44
  • 95
Rivu Chakraborty
  • 1,372
  • 2
  • 12
  • 37
  • Thanks for the answer. This is almost right, I had to ad the type in the parameters, and an override to the onItemClicked function. It worked in the end – Daniele Nov 08 '17 at 15:20