[英]Saving selected RadioButton's text in model class from recyclerview item
From RecyclerView
item, I am trying to save the selected RadioButton's text in model class. 从RecyclerView
项,我试图将所选RadioButton的文本保存在模型类中。 When I select a RadioButton
from 1st item, it's text is saved appropriately. 当我从第一项中选择一个RadioButton
,它的文本将被适当地保存。 Problem is, RadioButton's text at the same position from 8th item is also auto saved. 问题是,第8项中相同位置的RadioButton的文本也会自动保存。 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 : 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());
}
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. 问题在于,尽管代码看上去表面上是正确的,但实际上发生的是,当您调用holder.radioGroup.check()
,它会触发onCheckedChanged()
事件处理程序,就像用户启动它一样。
Since the views are recycled, the view at position 0 is being reused for position 8 in the list. 由于视图是回收的,因此位置0的视图将重新用于列表中的位置8。 So the call to check()
in onBindViewHolder()
will call onCheckedChanged()
, with the checked radio button from position 0 still checked (ie checkedId
and radioGroup. getCheckedRadioButtonId()
will return the ID of the radiobutton checked when the view was used at position 0). 因此,在onBindViewHolder()
对check()
的调用将调用onCheckedChanged()
,位置0处的选中单选按钮仍处于选中状态(即, checkedId
和radioGroup. getCheckedRadioButtonId()
将返回在视图中使用该视图时选中的单选按钮的ID radioGroup. getCheckedRadioButtonId()
位置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. 考虑答案的第一段,您将意识到这将(错误地)使用在位置0使用此视图时检查的radioButtonID
更新位置8的模型项。
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. 例如,您可以通过向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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.