Array Adapter notifyDataSetChanged() will not work
Asked Answered
S

5

6

I've been wasting too much time on this one so have to ask again. I've no idea why this is happening at all.

I have an array adapter (aAdapter) and an array list (aList) and I'm trying to put a clear button to erase the entries in a database and to clear the list.

My problem is that NotifyDataSetChanged() just wont work from inside my onlick method here:

public void clearDB(View view) {
    aList.clear();
    aAdapter.notifyDataSetChanged();
    HighScoresDB hsdb = new HighScoresDB(HighScoresActivity.this);
    hsdb.openDB();
    hsdb.clearDB();
    hsdb.closeDB();

}

It works from everywhere else though. I've even tried putting the clear and notifyDataSetChanged() in another method and calling it but that doesn't work either but did work when I called it from the onCreate....

Any ideas?

p.s. the database is being cleared.

Savaii answered 10/1, 2012 at 17:36 Comment(2)
have you tried notifyDataSetInvalidated() instead of notifyDataSetChanged()?Ecumenicism
I highly recommend using the CursorAdapter if you have a database. It is magical! You don't have to do notifyDataSetChanaged() it will just know that you've made a change to the database and update all on its own.Rutty
L
12

Firstly I find the Android adapter implementation very flawed. When it comes to performing anything bespoke there seems to be ambiguous accounts of how to use it and the official documentation doesn't clarify any of them. I would be very happy to be proved wrong with this.

The way I got consistent results when editing data in the view was as follows:

  • All changes to the underlying data structure being presented should be done in an AsyncTask which makes sense as you are changing things on the UI Thread and don't want to have concurrency issues.

  • Operations on the underlying data structures should be performed by calling adapter methods so if you have a ListAdapter then you use the add, remove and clear of the list adapter. This means the adapter manages view notifications etc. This generally leads to having to create a custom adapter as the methods available are limited (there isn't even an add all in sdk versions before 7). You also end up with your adapter acting as a big fat controller, although I am aware we shouldn't be viewing android as an MVC pattern it still seems wrong.

  • I have created apps where I bypass adapter calls to operate on the underlying data structure and it has worked all through results ended up unpredictable unless you tightly managed notifications to the view. Now I just call through the adapter.

So although I am not able to explain why in notifiyDataSetChanged doesn't work specifically in your onClick Method. I am hopefully providing useful information which might help you to get your app working as expected.

Lemmy answered 10/1, 2012 at 18:5 Comment(2)
Thanks for all the information I'll definitely implement some of your ideas. Sadly this is for a uni assignment and I'm running out of time as I'm going on holiday tomorrow so I think I'll try blindstuffs suggestion for now. However, I will be publishing this on to the market after I've handed this is so will try some of your ideas before then. :)Savaii
I agree, whatsthebeef!! I don't even use specific "documented functionality" anymore because I can't guarantee that they work at all times (even given the documentation provided). In fact, I've run into porcupine's issue before and I don't even use notifydatachanged() anymore either. :( I just make my own event handlers. It's sad, really. This comment relates specifically to Android adapters, not the SDK as a wholeAgist
E
9

While not pretty, you can just reinitialize the adapter instead of notifying it, I have seen that sometimes its the only way to make it work.

Eloisaeloise answered 10/1, 2012 at 17:38 Comment(3)
This was also the only way I could get it to clean itself.Lulu
I found reinitializing the adapter to be the only solution that worked! thanksStruthious
Yeah, happend to me today, too. I've had like 3 methods based on results from other activities, and in one of them notifying the adapter wouldn't do anything.Carnarvon
R
2

So a way I handled a similar problem to this is to basically reinitialize the adapter like blindstuff said.

    public class Example extends Activity{
        CustomAdapter adapter;
        ArrayList<ArrayList<String>> info = new ArrayList<ArrayList<String>>();
        final ListView list = (ListView) findViewById(R.id.listView_custom);
        adapter = new CustomAdapter(this, diceInfo.get(id));
        list.setAdapter(adapter);

Then in the onclick Listener

add.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                info.get(id).add("1,0,0,true");
                adapter = new CustomAdapter(Example.this, info.get(id));
                list.setAdapter(adapter);
            }
        });

The example doesn't have everything initialized but it gets to the point. I just make a new adapter and set it to the list view that I have. Works well.

Rutty answered 12/2, 2012 at 2:5 Comment(0)
D
0

Also ran into strange behaivior of the Adapter, when used in the dialog. Once adapter is updated (or underlying structure - both ways) and notifiyDataSetChanged dialog disappears without error or other trace in LogCat or debugging of Eclipse. Exactly the same code, once adapter is applied to the normal activity (ListView) works just fine.

Darnall answered 8/6, 2012 at 2:13 Comment(0)
R
0

I guess this thread isn't active anymore, but for future reference:

According to developer.android.com,

[onNotifyDataSetChanged()] Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.

Instead of having the Adapter tell the View to refresh itself, just update the data using adapter.clear() and adapter.add() and then force the ListView to update by calling listView.setAdapter(adapter) again.

Return answered 2/7, 2015 at 16:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.