带有游标适配器的列表视图中的复选框侦听器



我有一个与这篇文章非常相似的问题。在我的 ListView 的每一行中,我都有一个带有侦听器的复选框。侦听器更新数据行。

@Override
public void bindView(View v, Context context, Cursor c) {
    TextView tvA = (TextView) v.findViewById(R.id.adi_tv_activity);
    CheckBox cb = (CheckBox) v.findViewById(R.id.adi_cbox);
    tvA.setText(c.getString(c.getColumnIndex("name")));
    final long id = c.getLong(c.getColumnIndex("_id"));
    final Context ctx = context;
    cb.setOnCheckedChangeListener(new OnCheckedChangeListener(){
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            ObjDBF dbf = new ObjDBF(ctx); //Object thet update db
            if(isChecked) {
                dbf.tbActivitiesUpdateState(id, true);  
            } else {   
                dbf.tbActivitiesUpdateState(id, false);     
            }
        }               
    });
    if (c.getBoolean(c.getColumnIndex("state"))) {
        cb.setChecked(true);
    } else {
        cb.setChecked(false);
    }
}

我有2个问题。

  1. 滚动问题。移动列表时,我丢失了从屏幕上消失的行的复选框状态。
  2. 每当我使用 setChecked 时,都会调用侦听器,导致新的数据库更新。

对于解决滚动问题,我想在每次更新数据库时使用adapter.changeCursor,但是对于第二个问题,它会导致循环。

我也尝试使用一个数组,如上面链接帖子的第二个答案,但它使用方法getView od适配器,我有一个cursorAdapter并在newView和bindView中工作

如何解决问题?

编辑:Auselen解决方案有效,但它创建和破坏了很多听众,还有其他更有效的解决方案吗?

为避免在侦听器上触发回调,您应该逐个取消注册现有cb.setOnCheckedChangeListener(null)然后设置cb.setChecked(c.getBoolean(c.getColumnIndex("state")))然后再次cb.setOnCheckedChangeListener()

但是,您应该考虑使用该OnCheckedChangeListener的更好方法,因为您最终会创建比需要的更多的侦听器。

private SparseBooleanArray bolarray;
public class ViewHolder{
        CheckBox checked_displayName;
        int contact_id;
        String displayName;
        boolean isChecked=false;
    }
public void bindView(View v, Context context, Cursor cursor) 
{
ViewHolder viewHolder=new ViewHolder();
viewHolder.checked_displayName=(CheckBox) 
v.findViewById(R.id.checked_displayName);
viewHolder.displayName=cursor.getString(cursor.getColumnIndex(PROJECTION[0]));
viewHolder.checked_displayName.setText(viewHolder.displayName);
viewHolder.checked_displayName.setTag(viewHolder);
if(!bolarray.get(viewHolder.contact_id)){
            bolarray.put(viewHolder.contact_id, false);
            viewHolder.checked_displayName.setChecked(false);
            viewHolder.isChecked=false;
        }else{
            bolarray.put(viewHolder.contact_id, true);
            viewHolder.checked_displayName.setChecked(true);
            viewHolder.isChecked=true;
        }   

最新更新