从recyclerview项目中保存模型类中选定的RadioButton文本

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从recyclerview项目中保存模型类中选定的RadioButton文本相关的知识,希望对你有一定的参考价值。

RecyclerView项目,我试图在模型类中保存选定的RadioButton文本。当我从第一个项目中选择RadioButton时,它的文本被正确保存。问题是,RadioButton在第8项的同一位置的文本也是自动保存的。如果我从第2项中选择单选按钮,则第9项的文本也会自动保存,依此类推。如何解决这个问题呢?

onBindViewHolder方法如下:

    @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()事件处理程序,就像用户启动它一样。

由于视图被回收,位置0的视图将被重用于列表中的位置8。因此,在check()中对onBindViewHolder()的调用将调用onCheckedChanged(),仍然检查位置0的已检查单选按钮(即checkedIdradioGroup. getCheckedRadioButtonId()将返回在位置0处使用视图时检查的无线电按钮的ID)。

真正的症结在于此

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

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

解决此问题的一种方法是区分用户启动的更改和绑定启动的更改。例如,您可以通过向ViewHolder添加字段来指示视图当前是否绑定。

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文本的主要内容,如果未能解决你的问题,请参考以下文章

如何从recyclerview适配器获取选定项目的数量?

从片段类中的对话框添加项目到recyclerview。

如何正确突出显示 RecyclerView 上的选定项目?

如何突出显示 Recycler View 的选定项目?

从 QAbstractTableModel 类中访问视图和代理模型?

RecyclerView Item Android Studio的弹出菜单功能