您的位置:首页 > 移动开发 > Android开发

Android ListView的一个坑,你可掉进去过?

2014-04-21 16:16 363 查看
需要的功能很简单,就是一个带checkbox的列表,提交时需要知道用户选择了那些项目,如下图:

private Map<String, Object> populateMap(String lblNo,
Map<String, Object>... maps) {

Map<String, Object> map = null;
if (maps.length > 0) {
map = maps[0];
} else {
map = new HashMap<String, Object>();
}

map.put("lblNo", lblNo);
map.put("my", map);
map.put("checked", true);
return map;
}


View Code

private void bindAdapter(){

int[] to = new int[] { R.id.lblNo,R.id.ckbIt };
String[] from = new String[] { "lblNo","my"};
adapter = new SimpleAdapter(this, datas, R.layout.activity_post_list_item,
from, to);
// =======添加删除事件=======
SimpleAdapter.ViewBinder binder = new SimpleAdapter.ViewBinder() {

private boolean supressEvent=false;

@Override
public boolean setViewValue(View view, Object data,
String textRepresentation) {
final Object d =  data;

if (view instanceof CheckBox) {

final Map map=(Map)d;
CheckBox ckb = (CheckBox) view;
Log.d("T", "->Map"+map);
//ckb.setTag(map);
supressEvent=true; //需要避免在这里触发OnCheckedChange事件监听处理
ckb.setChecked((Boolean)map.get("checked"));
supressEvent=false;

ckb.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

Log.d("T", "onCheckedChanged->Map"+map +" ischecked:" +isChecked);
if(supressEvent)return;
//Map map=(Map)buttonView.getTag();
map.put("checked", isChecked);

}
});

return true; //返回true表示不需要父类进行默认设置
//参考http://www.cnblogs.com/carmanloneliness/p/3500832.html
//http://www.cnblogs.com/carmanloneliness/p/3500832.html
}

return false;
}
};
adapter.setViewBinder(binder);

// =======End=======

lv.setAdapter(adapter);
}


刚开始时,没加上面红色注释那一句,发现运行时程序行为总不合要求。
后来发现是ckb在执行setChecked时会触发OnCheckedChange处理程序,
而SimpleAdapter采用的也是控件重用机制,就是当列表往上下拖时,那些被拖出屏幕外的控件会重用(绑定新的数据,参考代码里给的那链接),由于使用了final在执行ckb.setChecked((Boolean)map.get("checked")); 触发该控件的OnCheckedChange处理程序,而这个处理程序指向的数据项是前一次绑定的那行即前一次调用setViewValue传入的数据,这样就可能导致datas中的某个数据被意外修改,进而引起程序行为的不确定。

解决办法就是在执行ckb.SetChecked时做个标记,而事件处理程序根据这个标记排除拖动列表产生消息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐