简体   繁体   中英

Weird bug in my databases causing changes when none should happen

I think the easier way to describe my bug is by showing it in a video . But the general idea is that I use a database to keep track of which items in a list of checkboxes is checked off. Whenever I click on an item and activate that list's action mode, it immediately forget those changes, in spite of them having already made their way to the database. What makes this worse is when multiple items become afflicted with this bug, they end up forming a strange bit of circular logic, wherein one item in the database will become checked and the other will become unchecked, and the two will continue this in a cycle as actions are done on the list due to the checkboxes constantly cycling between a checked state and an unchecked state and thus triggering the checkbox's onCheckedChangedListener . There is no code in onListItemClick() that should be causing these changes to happen on either a list level or database level, and no code in onPrepareActionMode or onCreateActionMode that would reload the CursorLoader or manipulate the selected item. Can anyone help me figure out what's going on to cause this? (My implementation can be found in the video, but I also included it below.)

public class TaskCursorAdapter extends ResourceCursorAdapter{

public View newView(Context context, Cursor cursor, ViewGroup parent){
        final LayoutInflater inflater = LayoutInflater.from(context);
        final long assignedID = cursor.getInt(cursor.getColumnIndex(NagTasksDatabaseHelper.ID));
        View v = inflater.inflate(layout, parent, false);
        CheckBox taskCheckBox = (CheckBox)v.findViewById(R.id.taskCheckBox);
        TextView taskText = (TextView)v.findViewById(R.id.taskTitle);
        TextView taskNote = (TextView)v.findViewById(R.id.taskNote);
        if (cursor.getInt(cursor.getColumnIndex(NagTasksDatabaseHelper.CHECKED))==1){
            taskText.setPaintFlags(taskText.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
            taskNote.setPaintFlags(taskNote.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
        }
        taskCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                //Current method:

                AlertDialog.Builder builder = new AlertDialog.Builder(buttonView.getContext());
                builder.setCancelable(true);
                Log.i("TaskCursorAdapter", "CheckBox assignedID="+assignedID);
                if (assignedID!=-1) {
                    NagTasksDatabaseHelper helper = new NagTasksDatabaseHelper(buttonView.getContext());
                    if (isChecked) {
                        helper.checkOffTask(assignedID);
                        //builder.setMessage("Item "+assignedID+" checked");
                    } else {
                        helper.uncheckTask(assignedID);
                        //builder.setMessage("Item "+assignedID+" unchecked");
                    }
                    helper.close();
                } else {
                    builder.setMessage("No ID found. Try something else.");
                    builder.create().show();
                }
            } 
        });
        return v;
    }
    public void bindView(View v, Context context, Cursor cursor){
        CheckBox taskCheckBox = (CheckBox)v.findViewById(R.id.taskCheckBox);
        TextView taskText = (TextView)v.findViewById(R.id.taskTitle);
        TextView taskNote = (TextView)v.findViewById(R.id.taskNote);
        taskCheckBox.setChecked(cursor.getInt(cursor.getColumnIndex(NagTasksDatabaseHelper.CHECKED))==1);
        //final long assignedID = v.getId();
        //v.setClickable(true);     
        //LinearLayout holder = (LinearLayout)v.findViewById(R.id.container);
        //holder.setClickable(true);
        //IdFromDb = c.getInt(c.getColumnIndex(NagTasksDatabaseHelper.ID));
        taskText.setText(cursor.getString(cursor.getColumnIndex(NagTasksDatabaseHelper.TASK)));
        taskNote.setText(cursor.getString(cursor.getColumnIndex(NagTasksDatabaseHelper.NOTE)));
        //isCheckedFromDb = c.getInt(c.getColumnIndex(NagTasksDatabaseHelper.CHECKED));
        //cursor = c;
    }

public class TaskListFragment extends SherlockListFragment implements ActionMode.Callback {
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    MenuInflater inflater = mode.getMenuInflater();
    inflater.inflate(R.menu.context_menu_single_choice, menu);
    mode.setTitle(R.string.activeActionMode);
    return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {

    return false;
}
public void onListItemClick(ListView l, View v, int position, long id){
    //super.onListItemClick(l, v, position, id);
    Log.i("NagTaskListFragment", "User clicked on "+id);
    if (mActionMode == null) {
        idForActionMode=id;
        mActionMode = getSherlockActivity().startActionMode(this);
    }
    if (l.getSelectedView() == v) {
        v.setSelected(false);
        mActionMode.finish();
        mActionMode = null;
        idForActionMode = -1;
    } else  if (l.getSelectedView() != null) {
        l.getSelectedView().setSelected(false);
        v.setSelected(true);
        idForActionMode = id;
        //onPrepareActionMode(mActionMode, mActionMode.getMenu());
        //Log.i("NagTaskListFragment", "selectedItemID = "+l.getSelectedItemId());
    } else {
        v.setSelected(true);
        idForActionMode = id;
        //Log.i("NagTaskListFragment", "selectedItemID = "+l.getSelectedItemId());
    }
}

So, I moved the setChecked() method to newView and that seemed to have fixed the issue. I'm not sure if that's the correct fix, but it works for now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM