Sebastien FERRAND
Sebastien FERRAND

Reputation: 2150

Updating a custom CursorAdapter performing a request inside getView fails

I'm still not getting exactly how a custom CursorAdapter should work, so after hard tries, here is the thing :

  1. I implement a listener on a button inside my getView().
  2. The listener launches a delete row event.
  3. To get to it, I use a singleton database where I can perform request from all classes (The purpose of a singleton actually)
  4. I usually update (insert and modify) from the activity class, so I just have to get the new database cursor and re-assign it to a new CursorAdapter, that I re-assign itself to the ListView.
  5. Here it's different : I'm inside the CursorAdapter class in the ListView method, and I don't know how to update my adapter from the inside.

For people who don't want to read my boring explanations, here is the code of the getView :

    @Override
public View getView(int position, View convertView, ViewGroup parent){
    convertViewParam = convertView;
    ViewHolder viewHolder = new ViewHolder();
    if (convertViewParam == null) {
        int type = getItemViewType(position);
        switch (type) {

        case TYPE_ADD_NOTE_TOP:
            convertViewParam = inflater.inflate(R.layout.add_note_top, null);
            viewHolder.contentNote = (EditText)convertViewParam.findViewById(R.id.add_note_top_id);
            break;
        case TYPE_ITEM:
            convertViewParam = inflater.inflate(R.layout.row_note, null);
            viewHolder.delete = (Button)convertViewParam.findViewById(R.id.delete);
            if (deleteMode){
                viewHolder.delete.setVisibility(View.VISIBLE);
            }else{
                viewHolder.delete.setVisibility(View.GONE);
            }

            viewHolder.contentNote = (TextView)convertViewParam.findViewById(R.id.note);

            getCursor().moveToPosition(position - 1);
            int currentPosition = getCursor().getPosition();
            Cursor c = getCursor();
            c.moveToPosition(currentPosition);

            ((TextView) viewHolder.contentNote).setText(c.getString(c.getColumnIndex("content_note")));
            int rowId = c.getInt(c.getColumnIndex("_id"));

            viewHolder.delete.setTag(new Integer(rowId));
            viewHolder.contentNote.setTag(new Integer(rowId));

            OnClickListener listener = new OnClickListener() {

                @Override
                public void onClick(View v) {
                    int thePosition = (Integer) v.getTag();

                    int posCurs = notesCursorAdapter.getCursor().getPosition();
                    NoteDataSource.getSingletonObject(context).deleteNote(thePosition, context);
                    notesCursorAdapter.changeCursor(NoteDataSource.getSingletonObject(context).getAllNotes());
                    notesCursorAdapter.notifyDataSetChanged();

                }
            };
            viewHolder.delete.setOnClickListener(listener);

            break;

        case TYPE_ADD_NOTE_BOTTOM:
            convertViewParam = inflater.inflate(R.layout.add_note_bottom, null);
            LinearLayout linearLayout = (LinearLayout)convertViewParam.findViewById(R.id.bottomLayout);
            linearLayout.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });
            break;
        }
        convertViewParam.setTag(viewHolder);
    } else {

        viewHolder = (ViewHolder)convertViewParam.getTag();
        if (viewHolder.contentNote!=null){
            if (viewHolder.contentNote.getTag() == convertViewParam.findViewById(R.id.note)){
                int test = (Integer) viewHolder.delete.getTag();
                System.out.println("current tag " + test);
                String txt = getCursor().getString(getCursor().getColumnIndex("content_note"));
                ((TextView) viewHolder.contentNote).setText(txt);
            }
        }


    }

    return convertViewParam;
}

I get the following error when I launch the delete event:

03-28 17:51:32.996: E/AndroidRuntime(7115): android.database.CursorIndexOutOfBoundsException: Index 2 requested, with a size of 2

If you want more info ask.

I'm looking for a bug fix or an just explanation, thanks.

Upvotes: 0

Views: 1544

Answers (2)

user
user

Reputation: 87064

It would help to know on which line you get the exception. First of all one bad thing is that you delete a note from the database based on a position int and after that you fetch again all the data and move the position on that cursor on the previous deleted position.

If you have 3 notes(and you show them in the list) in the database and you want to delete the last one this will happen:

  • the thePosition will be 2
  • you delete the note
  • fetch again all the notes from the database (the cursor will have 2 rows now because you deleted one)
  • move the cursor to thePosition (value 2)
  • the cursor has only 2 rows(numbered from 0) and you ask for row with the number 2
  • exception

If you want to delete a note then pass as a tag the _id for that row and use that to delete the note:

Cursor c = getCursor();
c.moveToPosition(position); 
long rowId = c.getLong(c.getColumnIndex("_id"));
viewHolder.delete.setTag(new Long(rowId));

Then in the onClick() method use that to delete the note and stop messing with the moveToPosition() on the cursor.

Upvotes: 1

Shubhayu
Shubhayu

Reputation: 13552

Thats a very well written problem statement. I have had this problem and broke my head over it. Try this.

  • In your Adapter make a listener, something like
public interface ItemDeletedListener(){
    public void itemDeleted(int position);
}
  • create an instance of ItemDeletedListener in your adapter, m_listener.

  • Write a setter function, setItemDeletedListener( ItemDeletedListener listener){}

  • In your getView(), onClickListener, call m_listener and pass the position that needs to be deleted.

Now in your Activity, Do the following.

  1. Implement the listener, that you created above.
  2. In your implementation, do the deletion work and then do a changeCursor() there.

Upvotes: 2

Related Questions