从recyclerview项目中将选定的RadioButton文本保存在模型类中 [英] Saving selected RadioButton's text in model class from recyclerview item

查看:100
本文介绍了从recyclerview项目中将选定的RadioButton文本保存在模型类中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

RecyclerView 项中,我试图将所选RadioButton的文本保存在模型类中.当我从第一项中选择 RadioButton 时,其文本将被适当保存.问题是,第8项中位于同一位置的RadioButton的文本也会自动保存.如果我从第二个项目中选择单选按钮,则第九个项目中的文本也会自动保存,依此类推.如何解决这个问题呢?

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方法如下:

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());

}

推荐答案

问题是,尽管表面上代码看起来正确,但实际上发生的是当您调用 holder.radioGroup.check(),它会触发 onCheckedChanged()事件处理程序,就像用户启动它一样.

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.

由于视图被回收,因此位置0的视图将重新用于列表中的位置8.因此,对 onBindViewHolder()中的 check()的调用将调用 onCheckedChanged(),其中从位置0开始选中的单选按钮仍处于选中状态(即 checkedId radioGroup.getCheckedRadioButtonId()将返回在位置0使用视图时选中的单选按钮的ID.

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).

真正的症结所在是

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

考虑答案的第一段,您将意识到这将(错误地)使用在位置0处使用此视图时检查过的 radioButtonID 更新位置8处的模型项.

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.

解决此问题的一种方法是区分用户发起的更改和绑定发起的更改.例如,您可以通过在 ViewHolder 中添加一个字段以指示视图当前是否绑定来完成此操作.

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

这篇关于从recyclerview项目中将选定的RadioButton文本保存在模型类中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆