Utoxin
Utoxin

Reputation: 448

Why isn't my ListView updating when I call notifyDataSetChanged()?

I'm close to finishing my first Android app, but I'm fighting with an odd bug when I delete items from the SQLite DB that feeds a ListView in my app. The item gets deleted, and if I switch away from the ListView and back, it updates, but until I do that, the list doesn't update.

I've posted most of the class in question here: https://gist.github.com/2025973, but here's the relevant callback starting at line 56 in the file:

builder.setPositiveButton(R.string.button_delete,
    new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            databaseConnector.deleteSimpleDie(arg3);
            storedDiceAdapter.notifyDataSetChanged();
        }
    });

What am I doing wrong here? I'm sure it's something simple. I originally had the delete in an Async, but then I couldn't call the notifyDataSetChanged() at all, because it has to happen from the thread that created the Cursor.

UPDATE

Okay, this is pretty ghetto ( I think... ) but I've got it working, finally. Someone want to tell me how horribly wrong this is? Basically, I'm just re-instantiating the whole CursorAdapter inside the callback. It solves the problem, but I suspect it has some negative side effects I'm not aware of.

builder.setPositiveButton(R.string.button_delete,
    new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            databaseConnector.deleteSimpleDie(arg3);

            String[] from = new String[] { "name", "description" };
            int[] to = new int[] { R.id.dice_name, R.id.dice_description };

            storedDiceAdapter = new SimpleCursorAdapter(StoredDice.this,
                    R.layout.stored_dice_item, null, from, to);
                setListAdapter(storedDiceAdapter);
        }
    });

Upvotes: 1

Views: 601

Answers (5)

user1499731
user1499731

Reputation:

If you ever set the underlying data set to something new, your reference that the adapter is holding onto, will break. For example, this would break the adapter:

    Globals.diceList = newDiceList;

When you want to fully change your data set, try something a little more like this, which will save you the trouble of having to constantly re-tool your adapter.

    Globals.diceList.clear();
    Globals.diceList.addAll(newDiceList);

Although in your case, you should be using a simple "remove" option instead. This will modify the contents of the list, without changing the location that it's referenced at. (Java is weird like that, I know.)

I wrote up a more in-depth look at it here.

Upvotes: 2

Utoxin
Utoxin

Reputation: 448

Well, as per the update on the question, it seems to be working. Not thrilled with that solution, but it's solved my immediate problem. Thank you everyone for the help.

Upvotes: 0

Calvin
Calvin

Reputation: 3312

I encountered similar problem earlier but I am not sure if it is exactly the same. You can give it a try.

  1. Create an Adapter class than inherit BaseAdapter or whichever Adapter that suit your needs.
  2. Create a public method such as setNewData(List) to update internal list.
  3. Whenever there is a change, update the internal list before you call notifyDataSetChanged().

It works for my case.

Slight modification to your code:

builder.setPositiveButton(R.string.button_delete,
new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int which) {
        databaseConnector.deleteSimpleDie(arg3); // Update DB
        storedDiceAdapter.setNewData(listData); // Update internal list
        storedDiceAdapter.notifyDataSetChanged(); // Notify changes
    }
});

Upvotes: 0

idiottiger
idiottiger

Reputation: 5177

i think your problem is the dialog:

public void onClick(DialogInterface dialog, int which) {
                        databaseConnector.deleteSimpleDie(arg3);
                        storedDiceAdapter.notifyDataSetChanged();
                    }

when show the dialog, your activity will be in onPause or onStop state , this time the activity dont refresh ui, so suggestion: when finish notifyDataSetChanged, you can dismiss the dialog, when onResume method, also invoke notifyDataSetChanged

Upvotes: 0

ghostbust555
ghostbust555

Reputation: 2049

Try adding listView.invalidate() after notifyDataSetChanged()

Upvotes: 0

Related Questions