Android中ListView自定义Adapter滚动时单选按钮状态不保存求助
解决ListView自定义Adapter单选按钮滚动后状态丢失的问题
嘿,这个问题我太熟悉了!本质是ListView的视图复用机制在搞鬼——当你滚动列表时,屏幕外的Item视图会被回收,用来显示新进入屏幕的Item,而你的Adapter没有在复用视图时正确恢复之前保存的选中状态,才导致状态丢失。下面是具体的修复方案:
问题根源分析
- 你的
getView方法只设置了单选按钮的监听器,但没有根据selectedAnswers里保存的值,给RadioButton设置正确的选中状态; - 视图复用时,旧的
OnCheckedChangeListener会被保留,导致滚动时意外触发监听器,篡改selectedAnswers里的数据; selectedAnswers被设为static,这会导致多个Adapter实例共享同一数据,容易引发状态混乱。
修复后的完整CustomAdapter代码
import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.CompoundButton; import android.widget.RadioButton; import android.widget.TextView; import java.util.ArrayList; public class CustomAdapter extends BaseAdapter { Context context; String[] questionsList; ArrayList<String> selectedAnswers; // 去掉static,避免多实例数据冲突 LayoutInflater inflter; public CustomAdapter(Context applicationContext, String[] questionsList, ArrayList<String> array) { this.context = applicationContext; this.questionsList = questionsList; // 复制传入的初始数据,避免外部修改影响Adapter内部状态 this.selectedAnswers = new ArrayList<>(array); inflter = LayoutInflater.from(applicationContext); } @Override public int getCount() { return questionsList.length; } @Override public Object getItem(int i) { return questionsList[i]; } @Override public long getItemId(int i) { return i; } @Override public View getView(final int i, View view, ViewGroup viewGroup) { ViewHolder holder; // 使用ViewHolder模式优化视图复用性能,同时避免重复查找控件 if (view == null) { view = inflter.inflate(R.layout.radio_group_item, viewGroup, false); holder = new ViewHolder(); holder.question = view.findViewById(R.id.question); holder.yes = view.findViewById(R.id.yes); holder.no = view.findViewById(R.id.no); view.setTag(holder); } else { holder = (ViewHolder) view.getTag(); } // 先移除旧监听器,避免复用视图时触发旧逻辑篡改数据 holder.yes.setOnCheckedChangeListener(null); holder.no.setOnCheckedChangeListener(null); // 根据保存的状态,设置当前Item的单选按钮选中状态 String currentAnswer = selectedAnswers.get(i); holder.yes.setChecked("Yes".equals(currentAnswer)); holder.no.setChecked("No".equals(currentAnswer)); // 重新设置监听器,处理用户选择逻辑 holder.yes.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { selectedAnswers.set(i, "Yes"); // 同步取消另一个按钮的选中状态,避免同时选中 holder.no.setChecked(false); } } }); holder.no.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { selectedAnswers.set(i, "No"); // 同步取消另一个按钮的选中状态 holder.yes.setChecked(false); } } }); holder.question.setText(questionsList[i]); return view; } // ViewHolder内部类,缓存控件引用 static class ViewHolder { TextView question; RadioButton yes; RadioButton no; } }
额外优化建议
- 在你的
OnooltActivity2中,移除不必要的simpleList.onSaveInstanceState()和simpleList.onRestoreInstanceState()调用,因为Adapter已经通过selectedAnswers保存了状态; - 确保
getDavaa()方法完成数据加载后,再初始化Adapter或者调用customAdapter.notifyDataSetChanged(),避免数据未加载完成就渲染视图; - 如果
questions数组是动态加载的,记得在数据准备好后再赋值给Adapter,避免空指针异常。
这样修改后,ListView滚动时就能正确保存和恢复每个Item的单选按钮状态了!
内容的提问来源于stack exchange,提问作者Amarsaikhan
相关产品推荐
相关产品推荐

