1 回答
TA贡献1827条经验 获得超9个赞
问题是,尽管代码表面上看起来是正确的,但实际发生的是,当您调用 时holder.radioGroup.check(),它会触发您的onCheckedChanged()事件处理程序,就像用户启动它一样。
由于视图被回收,位置 0 的视图被重用于列表中的位置 8。所以调用check()inonBindViewHolder()将调用onCheckedChanged(),从位置 0 选中的单选按钮仍然被选中(即checkedId,radioGroup. getCheckedRadioButtonId()当视图在位置 0 使用时,将返回选中的单选按钮的 ID)。
真正的关键是这个
models.get(clickedPos).setChecked(radioButtonID);
考虑答案的第一段,您会意识到这将(错误地)更新位置 8 处的模型项,radioButtonID并使用在位置 0 处使用此视图时检查的 。
解决此问题的一种方法是区分用户发起的更改和绑定发起的更改。例如,您可以通过向 中添加一个字段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;
}
添加回答
举报
