Home > Enterprise >  Data disappears when scrolling in recycler view
Data disappears when scrolling in recycler view

Time:03-16

Good day. So I currently have data in my recycler view. It is for now only static data. I still have to do the code where I import. My problem however is I have a button that changes the background of a text view. This happens in my adapter. And when I scroll through my list the bg color change gets reverted back to what it was before the button click. I have read a lot of similar problems but could not really find one that explains clearly or work for me. From what I read the data gets reset to the static data because it is currently happening in my onBindViewHolder and I think this changes the data on every new data read(scrolling). I read that I should create a link or a listener and then call it. But It does not make sense to me because if a link is called the same amount of times as the code is executed then it will be the same will it not. Maybe having a condition listener but not sure if this is the way to go.

I am somewhat new to android and kotlin. Have been working with it for a month now. I dont know everything I am doing but I got given a deadline. So sadly there was no time to go and learn the basics. Thank you for any and all help. Please let me know if you need any additional code/information

my adapter

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RowViewHolder {
        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.table_list_item, parent, false)
        return RowViewHolder(itemView)


    }

    private fun setHeaderBg(view: View) {
        view.setBackgroundResource(R.drawable.table_header_cell_bg)
    }

    private fun setContentBg(view: View) {
        view.setBackgroundResource(R.drawable.table_content_cell_bg)
    }

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

      //  (TableViewAdapter.DataviewHolder) .bind()

        val rowPos = holder.adapterPosition



        if (rowPos == 0) {
            // Header Cells. Main Headings appear here
            holder.itemView.apply {
                setHeaderBg(txtWOrder)
                setHeaderBg(txtDElNote)
                setHeaderBg(txtCompany)
              //  setHeaderBg(txtAddress)
                setHeaderBg(txtWeight)
                setHeaderBg(txtbutton1)
                setHeaderBg(txtbutton2)
                setHeaderBg(txttvdone)


                txtWOrder.text = "WOrder"
                txtDElNote.text = "DElNote"
                txtCompany.text = "Company"
               // txtAddress.text = "Address"
                txtWeight.text = "Weight"
                txtbutton1.text = "Delivered"
                txtbutton2.text = "Exception"
                txttvdone.text = ""
            }
        } else {
            val modal = Tripsheetlist[rowPos - 1]

            holder.itemView.apply {
                setContentBg(txtWOrder)
                setContentBg(txtDElNote)
                setContentBg(txtCompany)
              //  setContentBg(txtAddress)
                setContentBg(txtWeight)
                setContentBg(txtbutton1)
                setContentBg(txtbutton2)
                setContentBg(txttvdone)

                txtWOrder.text = modal.WOrder.toString()
                txtDElNote.text = modal.DElNote.toString()
                txtCompany.text = modal.Company.toString()
              //  txtAddress.text = modal.Address.toString()
                txtWeight.text = modal.Weight.toString()
                txtbutton1.text = modal.Button1.toString()
                txtbutton2.text = modal.Button2.toString()
                txttvdone.text = modal.tvdone.toString()
            }
        }

        holder.apply {
            txtbutton1.setOnClickListener {
                Log.e("Clicked", "Successful delivery")
                txttvdone.setBackgroundResource(R.color.green)
                txttvdone.setText("✓")
            }
            txtbutton2.setOnClickListener {
                Log.e("Clicked", "Exception on delivery")
                txttvdone.setBackgroundResource(R.color.orange)
                txttvdone.setText("x")
            }



        }



    }

    class RowViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
         
     val txttvdone:TextView = itemView.findViewById<TextView>(R.id.txttvdone)
         val txtbutton1:Button = itemView.findViewById<Button>(R.id.txtbutton1)
         val txtbutton2:Button = itemView.findViewById<Button>(R.id.txtbutton2)
     }      class MyViewHolder(val view: View) : RecyclerView.ViewHolder(view){


        var txtbutton1 = view.findViewById<Button>(R.id.txtbutton1)
        val txtbutton2:Button = itemView.findViewById<Button>(R.id.txtbutton2)
        var txttvdone = view.findViewById<TextView>(R.id.txttvdone)
    }

I tried (TableViewAdapter.DataviewHolder) .bind() doing this and creating another class as I saw that was done in another thread(Why do values ​disappear after scrolling in Recycler View?) Its a lot like my problem. I just can't seem to implement his solution to make mine work. ( don't understand his solution fully)

//I am also aware that I am using android extensions which will expire at the end of the year. But for now it works and once I have the code up and running I will start to move over to the newer versions of kotlin.

CodePudding user response:

A RecyclerView, as its name implies, will recycle the views when they go off screen. This means that when the view for an item comes into view, it gets recreated and the onBindViewHolder() is called to fill in the details.

Your onClickListener inside your adapter changes the background of one of the subviews for your cell view. However, that cell will be redrawn if it leaves the screen and comes back.

To get around this, your onClickListener should be changing a property on the data item, and your onBindViewHolder should check that property to determine what background color to display for the subview:

enum class DataState {
    Unselected,
    Success,
    Failure
}
data class DataItem(var state: DataState = DataState.Unselected)

class MyAdapter : RecyclerView.Adapter<MyViewHolder>() {
    var dataItems: List<DataItem> = emptyList()

    fun updateData(data: List<DataItem>) {
        dataItems = data
        notifyDataSetChanged()
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val dataItem = dataItems[position]
        holder.txttvdone.apply {
            setBackgroundResource(when (dataItem.state) {
                DataState.Unselected -> android.R.color.transparent
                DataState.Success -> R.color.green
                DataState.Failure -> R.color.orange
            })
            text = when (dataItem.state) {
                DataState.Unselected -> ""
                DataState.Success -> "✓"
                DataState.Failure -> "x"
            }
        }

        holder.apply {
            txtbutton1.setOnClickListener {
                Log.e("Clicked", "Successful delivery")
                dataItem.state = DataState.Success
                notifyDataSetChanged()
            }
            txtbutton2.setOnClickListener {
                Log.e("Clicked", "Exception on delivery")
                dataItem.state = DataState.Failure
                notifyDataSetChanged()
            }
        }
    }
}
  • Related