从recyclerview项目中将选定的RadioButton文本保存在模型类中 [英] Saving selected RadioButton's text in model class from recyclerview item
问题描述
从 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屋!