Search code examples
javakotlinandroid-recyclerviewadapterandroid-adapter

Unresolved reference: textView


I'm trying to create a recyclerView, but when I try to reference my textView I get an error that says Unresolved Reference: textViewTitle, I have tried many ways and I could not, I appreciate your wise help.

class RecyclerAdapter(private val userList: ArrayList<Sitios> = ArrayList()) :
    RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.card_view, parent, false)

        return ViewHolder(v)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

        //Unresolved reference: textViewTitle
        holder.itemView.textViewTitle.text = userList[position].description
    }

    override fun getItemCount(): Int = userList.size

Solution

  • holder.itemView is the View you pass into your ViewHolder class when onCreateViewHolder runs. It's just a normal View, and there's no field called textViewTitle in that class, which is what you're trying to reference with holder.itemView.textViewTitle - that's why it's saying the reference is unresolved

    What you probably want to do is find a TextView with that ID within itemView's hierarchy, so you need to do

    holder.itemView.findViewById<TextView>(R.id.textViewTitle)
    

    or whatever the ID is. But typically, people will put fields in the ViewHolder class instead, set them by doing the lookup once, and then you can just access them like you're trying to do:

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        lateinit var textViewTitle : TextView
    }
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.card_view, parent, false)
        // or you could make the TextView a val in the ViewHolder's constructor and just pass it in instead of setting it after creation
        val holder = ViewHolder(v)
        holder.textViewTitle = v.findViewById<TextView>(R.id.textViewTitle)
        return ViewHolder(v)
    }
    
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // now the reference is a field on the ViewHolder
        holder.textViewTitle.text = userList[position].description
    }
    

    this is better because onBindViewHolder runs every time a new item scrolls into view, so you don't want to be doing lots of findViewByIds when you can just do it once


    If you're doing it the field way, like up there, instead of making the view references constructor parameters (which can get messy when you have a few) I'd write it more like this:

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.card_view, parent, false)
        return ViewHolder(v).apply {
            textViewTitle = v.findViewById(R.id.textViewTitle)
            // and any other views you need to set up
        }
    }
    

    it looks pretty neat, especially with several views!