Search code examples
androidkotlinandroid-radiobuttonandroid-radiogroup

How to handle onCheckedChangeListener in RadioGroup inside Recyclerview which is called while setting the state of the RadioGroup?


I am trying to add a radiogroup with 4 radiobuttons in a recyclerview. I am saving the state in room and taking it in adapter to set the appropriate radiobutton. While doing this I am using radiogroup.check() and radiogroup.clearchek() method inside onBindViewHolder and this will then call radiogroup.setOnCheckedChangeListener automatically whenever we scroll the recyclerview. My code is like this

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        question = quesions[position]
        qTitle = question.question!!
        holder.textTestQuestion.text = "" + (number + position) + " " + question.question;
        holder.answerFirst.text = "a. " + question.answers?.get(0).toString()
        holder.answerSecond.text = "b. " + question.answers?.get(1).toString()
        holder.answerThird.text = "c. " + question.answers?.get(2).toString()
        holder.answerFourth.text = "d. " + question.answers?.get(3).toString()

        holder.radio_group.setTag(position)

        if (question.rightAnswer != null) {
            holder.radio_group.check(question.rightAnswer!!)
        } else {
            holder.radio_group.clearCheck()
        }

        holder.radio_group.setOnCheckedChangeListener(object : RadioGroup.OnCheckedChangeListener {
            override fun onCheckedChanged(group: RadioGroup?, checkedId: Int) {
                        val pos = group?.getTag() as Int
                        val ques = quesions[pos]
                        val chid = group.checkedRadioButtonId

                        ques.rightAnswer = checkedId
                        ques.answered = true
                       Observable.just(question).subscribeOn(Schedulers.io()).subscribe { t: Question? ->
                            qnADao.saveQuestion(ques)

                        }

            }

        })

    }

I have tried every solution out here on stackoverflow like checking for -1 in the radiogroup.checkedRadioButtonId and then also radiogroup.isPressed nothing is working for me. So any help would be appreciated. Thanks


Solution

  • Using onClickListener instead of setOnCheckedChangeListener is a solution. But if you do view.performClick() inside bind() in future then this will happen again.

    The listeners that you set to the views are still active even after the view goes off the screen and recycled back to a new row.

    When scrolling upwards, the view that goes off the screen is taken by the RecyclerView and attaches it to the bottom row and hands over to you to bind it with a new data. This view still has that event listeners attached in it. When you call the line holder.radio_group.check(), the listener that was attached previously will execute.

    You can remove the listener first, then check/uncheck the radiogroup, and then set the new event listener to the radiogroup. In your code, like this:

    holder.radio_group.setOnCheckedChangeListener(null)    // <----- This line added.
    
    if(question.rightAnswer != null) {
        holder.radio_group.check(question.rightAnswer!!)
    } else {
        holder.radio_group.clearCheck()
    }
    
    holder.radio_group.setOnCheckedChangeListener(object : RadioGroup.OnCheckedChangeListener { ..... })