之前有过一篇博客Android中ListView包含CheckBox时滑动丢失选中状态的解决写过类似的问题,今天总结个另一种解决办法。

在工作中有时会遇到含有CheckBox 的ListView/Recyclerview时,发现当初始化CheckBox的状态后, 滚动ListView/Recyclerview,其中CheckBox 的选中状态不停的发生变化。最后发现原因 是ListView/Recyclerview滚动时自动调用 onCheckedChanged 导致的。

解决办法是在自定义的Adapter的getView/onBindViewHolder方法中这样写就行了。

//在初始化CheckBox状态和设置状态变化监听事件之前,先把状态变化监听事件设置为null  
holder.checkBox.setOnCheckedChangeListener(null);
//然后设置CheckBox状态
if(isChecked) {
holder.checkbox.setChecked(true);
} else {
holder.checkbox.setChecked(false);
}
//然后设置状态变化监听事件
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
//...
}else{
//....

分析:

  1. CheckBox在执行setChecked时会触发OnCheckedChange处理程序;
  2. Adapter采用的是控件重用机制,就是当列表往上下拖时,那些被拖出屏幕外的控件会重用,由于该item获取到的数据项(dataList.get(index))往往使用了final,所以在执行CheckBox.setChecked(true/false); 触发该控件的OnCheckedChange处理程序,而这个处理程序指向的数据项是前一次绑定的那行数据,这样就可能导致dataList中的某个数据被意外修改,进而引起程序行为的不确定。