此异常的主要原因是:Adapter的数据改变了,但没有及时的通知notifyDataSetChanged()。
为了避免此问题,将Activity中的原始数据和Adapter中的数据进行分离,当业务数据在Activity中变化变化时,不影响到Adapter。
public class SdcardListAdapter extends BaseAdapter {
private Context context;
private List dataList = new ArrayList();
public SdcardListAdapter(Context context, List data) {
this.context = context;
this.dataList.addAll(data);
}
public void setData(List data){
this.dataList.clear();
this.dataList.addAll(data);
}
后来发现:其实如上的操作并没有完全分离两边的数据。当在Adapter中改变数据dataList中的item值时,Acvitity中对应的数据也会发生变化。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
ViewHolder holder = null;
if (view == null) {
LayoutInflater inflater = LayoutInflater.from(context);
view = inflater.inflate(R.layout.sdcard_list_item, null);
holder = new ViewHolder();
holder.titleView = (TextView) view.findViewById(R.id.sdcard_title);
holder.choseView = (CheckBox) view.findViewById(R.id.sdcard_chose);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
final SdcardSimpleInfo info = dataList.get(position);
holder.titleView.setText(info.getTitle());
holder.choseView.setChecked(info.isChose());
holder.choseView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
info.setChose(!info.isChose());
}
});
return view;
}
之前错误的认为ArrayList.addAll(...)是深拷贝,其实是浅拷贝,只拷贝了源List中的Item地址,源List和目标List中的元素指向相同的Item地址,因此操作其中一个会体现到另一个。在此处也是一个好处,因为在Adapter中的操作结果,可以在Activity中直接得到,不用再从Adapter中函数获取。
ArrayList.addAll(...)的实现代码如下:
public boolean addAll(Collection extends E> collection) {
Object[] newPart = collection.toArray();
int newPartSize = newPart.length;
if (newPartSize == 0) {
return false;
}
Object[] a = array;
int s = size;
int newSize = s + newPartSize; // If add overflows, arraycopy will fail
if (newSize > a.length) {
int newCapacity = newCapacity(newSize - 1); // ~33% growth room
Object[] newArray = new Object[newCapacity];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
}
System.arraycopy(newPart, 0, a, s, newPartSize);
size = newSize;
modCount++;
return true;
}
参考:http://blog.sina.com.cn/s/blog_3e333c4a01011kpd.html