Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manage deleting an item on a CursorAdapter

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);
        (...)
    }
    (...)
}
like image 514
colletjb Avatar asked Mar 05 '13 15:03

colletjb


4 Answers

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);
    
like image 126
JPMagalhaes Avatar answered Nov 16 '22 07:11

JPMagalhaes


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

If you want real performance use the AsyncTaskLoader.

like image 39
Loxley Avatar answered Nov 16 '22 08:11

Loxley


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.

like image 22
tolgap Avatar answered Nov 16 '22 09:11

tolgap


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()

like image 1
Steven Byle Avatar answered Nov 16 '22 09:11

Steven Byle