How to manage deleting an item on a CursorAdapter
Asked Answered
S

4

5

I'm currently facing a stupid issue. I've a listview with a custom adapter (extending CursorAdapter).

It displays a custom view with different buttons (share, like, delete). For the delete button, it has an alertdialog to confirm the removal of the item. When the user confirms, the item is deleted from the db. Everything works fine until here.

My question is, how can I update my listview efficiently with my new dataset?

Thanks a lot for your help.

Code:

public class CommentCursorAdapter extends CursorAdapter{
    (...)
    @Override
    public void bindView(View view, Context arg1, Cursor cursor) {
    (...)
        holder.list_item_comment_discard_btn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            final String _id = v.getTag().toString();
            AlertDialog.Builder builder = new    AlertDialog.Builder(mActivity);
            builder.setTitle("Delete");
            builder.setMessage("Do you want to delete "+_id);
            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    // User clicked OK button
                    DBAdapter dba = new DBAdapter(mActivity);
                    dba.open();
                    dba.remove(_id);
                    Log.i("TAAG", "removed: "+_id);
                    dba.close();    

                // How to update the listview ??                                    
                }
            });
            builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    // User cancelled the dialog
                }
            });

            AlertDialog d = builder.create();
            d.show();
        }
        });
        holder.list_item_comment_discard_btn.setTag(_id);
        (...)
    }
    (...)
}
Stoppage answered 5/3, 2013 at 15:9 Comment(0)
B
9

If you use LoaderManager to manage the lifecycle of your cursors (that is the right way to do this) you need only to call restartLoader and then (re)set the cursor of your adapter in onLoadFinished. Your listview will be reloaded with updated data.

The management of a cursor in your activity or fragment should be done in a very simple and straightforward way:

  • In order to initialize your cursor:

    public void onCreate(Bundle savedInstanceState) { // or onStart
    // ...
    this.getLoaderManager().initLoader(MY_CURSOR_ID, null, this);
    // ...
    }
    
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // TODO: create a cursor loader that will load your cursor here
    }
    
    public void onLoadFinished(Loader<Cursor> arg0, final Cursor arg1) {
    // TODO: set your cursor as the cursor of your adapter here;
    }
    
    public void onLoaderReset(Loader<Cursor> arg0) {
    // TODO: set null as the cursor of your adapter and 'free' all cursor
    // references;
    }
    
  • And then, when you need to reload your data:

    this.getLoaderManager().restartLoader(MY_CURSOR_ID, null, this);
    
Benedikt answered 6/3, 2013 at 4:49 Comment(1)
i implemented an interface on my adapter to notify the list when an item is deleted, then as you suggest, i restart my loader. It works now ;)Stoppage
H
1

Call cursor.requery(); notifyDataSetChanged(); .

If you want real performance use the AsyncTaskLoader.

Herzog answered 5/3, 2013 at 15:17 Comment(0)
C
1

Just requery the Cursor like this:

public void onClick(DialogInterface dialog, int id) {
    // User clicked OK button
    DBAdapter dba = new DBAdapter(mActivity);
    dba.open();
    dba.remove(_id);
    Log.i("TAAG", "removed: "+_id);
    dba.close();    
    cursor.requery();
    notifyDataSetChanged();                                   
}   

and then call notifyDataSetChanged() to tell the Adapter that the data has changed, and it has to build the adapter again.

This will be an intense operation if the requery takes long. Consider doing it in another thread.

Cu answered 5/3, 2013 at 15:17 Comment(2)
I tested, but it didn't work. Furthermore, cursor.requery() is deprecated :(Stoppage
Well if it's deprecated, you could just as well request a new cursor using an AsyncTaskLoader like @Herzog mentioned in the answer below.Cu
P
1

After you delete the item in the DB, call notifyDataSetChanged on your CommentCursorAdapter, granted with this anonymous inner class you are using you will need a final reference to this since this in inside your CursorAdapter. This should trigger a refresh of your ListView.

http://developer.android.com/reference/android/widget/BaseAdapter.html#notifyDataSetChanged()

Pocahontas answered 5/3, 2013 at 15:18 Comment(1)
I tried this without success :'( : builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User clicked OK button DBAdapter dba = new DBAdapter(mActivity); dba.open(); dba.remove(_id); Log.i("TAAG", "removed: "+_id); dba.close(); cursor.requery(); mInstance.notifyDataSetChanged(); } });Stoppage

© 2022 - 2024 — McMap. All rights reserved.