user1341676
user1341676

Reputation:

ArrayAdapter, ListView, creating and updating contents

I posting this again, trying to make the question/problem clearer:

ListView lv;
List<Item> items;
Localstorage ls;
RemoteStorage rs;
ItemArrayAdapter adapter;

...

getShoppingList();  // <--- this method populates the items ArrayList
adapter = new ItemArrayAdapter(getApplicationContext(), R.layout.item_listitem, 
                               items);  // <--- Create an ArrayAdapter and insert the 
                                        //      ArrayList...
lv.setAdapter(adapter);

The code so far populates the ArrayList items, creates an adapter and adds items to this, and then shows it in the ListView lv. So far, so good.

However, the getShoppingList() method is run several times, updating the ArrayList items. And instead of recreating the adapter every time this happens, I'd like to just update it and display the updated contents in the ListView lv.

What I'm trying is this:

OnClick method for the "Update" button:

public void onClick(View v) {
    if (((Button)v).getText().equals("Update")) {
        try {
            tmpitems = rs.getNewEntries(cdate, latestitem);
            if (tmpitems.size() > 0) {
                updateFooter(tmpitems.size() + " new items found on server!");
                ls.UpdateLocalList(tmpitems);
                getShoppingList();               
                updateLatestItem(); 
                adapter.setNotifyOnChange(true);    //
                adapter.notifyDataSetChanged();     // THIS IS WHAT ISN'T WORKING
                lv.setAdapter(adapter);             //
            } else {
                updateFooter("No new items found on server.");
            }
        } catch (NullPointerException npe) {
            Log.e(DEBUG_TAG, "NPException i onClick(): " + npe.toString());
            updateFooter("No new items found on server.");
        }

However, the lines for updating the adapter (after items have been updated) does absolutely nothing. I know that items is updated, because it's also written to a file, so the problem is not there. Besides, if I replace the lines for updating the adapter with lines for recreating it, it works nicely.

Update (sept. 16, 2012):

private void getShoppingList () {
    items = ls.getShoppingList(SHOPPINGLIST_FILE, cdate);
}

The ls.getShoppingList() method:

public List<Item> getShoppingList (String filename, String date) {
    String next[] = {};
    List<Item> nlist = new ArrayList<Item>();

    try {
        InputStream in = ctx.openFileInput("shoppinglists.csv");
        InputStreamReader isr = new InputStreamReader(in);
        CSVReader reader = new CSVReader(isr);

        for(;;) {
            next = reader.readNext();
            if(next != null) {
                if (next[0].equals(date)) {
                    nlist.add(new Item(next[0], next[1], next[2], 
                    next[3], next[4], next[5]));
                }
            } else {
                break;
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
        Log.e(DEBUG_TAG, "IOException in List(): " + e.toString());
    }

    return nlist;
}

---------- Original post ------------------

I have a ListView lv with an ArrayAdapter for displaying rows of items.

List<Item> items;
ItemArrayAdapter adapter;
adapter = new ItemArrayAdapter(getApplicationContext(), R.layout.item_listitem, 
                               items);

lv.setAdapter(adapter);

This works nicely. The items arraylist is populated, and the adapter shows the contents in the ListView.

However, then I do some stuff that updates the ArrayList items. And then I want to update the adapter and the ListView. But this code,

adapter.setNotifyOnChange(true);
adapter.notifyDataSetChanged();

obviously doesn't do it. So, how do I update the adapter and hence the ListView with the updated items ArrayList? Without reinitializing the adapter, that is?

EDIT:

The items ArrayList is updated thusly:

if (((Button)v).getText().equals("Update")) {
    try {
        tmpitems = rs.getNewEntries(cdate, latestitem);
            if (tmpitems.size() > 0) {
                ls.UpdateLocalList(tmpitems);
                getShoppingList();
                refreshList();
           } else {
           updateFooter("No new items found on server.");
       }
    } catch (NullPointerException npe) {
        Log.e(DEBUG_TAG, "NPException i onClick(): " + npe.toString());
        updateFooter("No new items found on server.");
    }
}

refreshList() {
    adapter.setNotifyOnChange(true);
    adapter.notifyDataSetChanged();
}

- New items are read into the tmpitems ArrayList. - If the number of new items are >0, a local file is updated with the tmpitems. - Then the items ArrayList is updated from the local file (with the getShoppingList() method, which adds the new entries) - Then I try running the refreshList() method, which is supposed to update the adapter, as mentioened above.

The items ArrayList IS updated, and the local files are updated. It's just the update method on the adapter I can't get to work. When initializing the adapter, the items are shown in the ListView - when updating it, the new contents are not.

Upvotes: 1

Views: 10348

Answers (1)

Vasily Sochinsky
Vasily Sochinsky

Reputation: 4011

Use ((ItemArrayAdapter)lv.getAdapter()).notifyDataSetChanged() instead of adapter.notifyDataSetChanged()

Update: The thing is that notifyDataSetChanged() works only when the data inside the adapter has changed, and it rerenders the list. In your case you change the data externally, so you have to change the data inside the adapter.

You will need to replace nlist.add(...) with insert() and remove() methods of the adapter: official reference

Some clarification on how it works: when you initialize adapter, it just sticks the items array you've passed to it to it's own ones. It is not aware of the changes made to your items array anymore.

Upvotes: 2

Related Questions