Saving selected RadioButton's text in model class from recyclerview item

隐身守侯 提交于 2019-12-25 00:13:05

问题


From RecyclerView item, I am trying to save the selected RadioButton's text in model class. When I select a RadioButton from 1st item, it's text is saved appropriately. Problem is, RadioButton's text at the same position from 8th item is also auto saved. If I select radio button from 2nd item, text from 9th item is also auto saved, and so on. How to solve this problem?

onBindViewHolder method is given below :

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {

    ...

    holder.radioGroup.setTag(position);
    holder.radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {

            int radioButtonID = group.getCheckedRadioButtonId();
            RadioButton radioButton = (RadioButton) group.findViewById(radioButtonID);
            int clickedPos = (Integer) group.getTag();
            models.get(clickedPos).setChecked(radioButtonID);

            if (radioButtonID > 0){
                models.get(clickedPos).setSelectedAns(radioButton.getText().toString());
            }

        }
    });
    holder.radioGroup.check(models.get(position).getChecked());
    Log.d("TAG", "At position " + position + " selected : " + models.get(position).getSelectedAns());

}

回答1:


The problem is that although the code looks correct on the surface, what's actually happening is that when you call holder.radioGroup.check(), it triggers your onCheckedChanged() event handler just the same as if the user had initiated it.

Since the views are recycled, the view at position 0 is being reused for position 8 in the list. So the call to check() in onBindViewHolder() will call onCheckedChanged(), with the checked radio button from position 0 still checked (i.e. checkedId and radioGroup. getCheckedRadioButtonId() will return the ID of the radiobutton checked when the view was used at position 0).

The real crux is this

models.get(clickedPos).setChecked(radioButtonID);

Consider the first paragraphs of the answer, and you'll realize that this will (incorrectly) update the model item at position 8 with the radioButtonID that was checked when this view was used at position 0.

One way to solve this is to distinguish between a user-initiated change and a binding-initiated change. You can for example do this by adding a field to the ViewHolder to indicate if the view is currently binding.

class ViewHolder extends RecyclerView.ViewHolder{
    TextView selectedAnswer;
    RadioGroup radioGroup;

    boolean isBinding;

    ViewHolder(View itemView) {
        super(itemView);

        radioGroup = itemView.findViewById(R.id.radioGroup);

        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                int position = getAdapterPosition();

                RadioButton radioButton = (RadioButton) group.findViewById(checkedId);

                /* Only update the model when onCheckedChange() was initiated by the user clicking
                   a radio button, not when the adapter is binding the view. In that scenario, we
                   are only interested in passing information FROM the model TO the view. */
                if( !isBinding ) {
                    models.get(position).setChecked(checkedId);
                    models.get(position).setSelectedAns(radioButton != null ? radioButton.getText().toString() : "");
                }

                selectedAnswer.setText(  models.get(position).getSelectedAns() );
            }
        });

        ...
    }
}

 

@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
    holder.isBinding = true;

    ...

    /* When calling check() here, we invoke onCheckedChanged(), which will
       update the textview that displays the selected answer - so no need to call
           holder.selectedAnswer.setText(  models.get(position).getSelectedAns() )
       from here */
    holder.radioGroup.check(models.get(position).getChecked());

    holder.isBinding = false;
}


来源:https://stackoverflow.com/questions/53013386/saving-selected-radiobuttons-text-in-model-class-from-recyclerview-item

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!