Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListView does not update when calling notifyDataSetChanged from a BaseAdapter

im am having difficulties to update a ListActivity when the underlying data changes.

I am using a custom (list) adapter (CustomListAdapter) derived vom BaseAdapter to fill a ListActivity with custom list elements (CustomListElement).

The elements in question can have their underlying data changed over time, either by user interaction or by changes in an underlying database. In order to announce said changes, the CustomListElement and CustomListAdapter objects can register DataSetObserver objects.

This is in essence done like this (unfortunately posting the entire code would be overkill):

public class CustomListElement extends DataSetObservable {

    protected Object value;

    public void setValue(Object newValue) {
         this.value = newValue;
         notifyChanged();
    }
}

Hence a CustomListElement provides registerDataSetObserver by inheritance from DataSetObservable and announces changes by means of it's notifyChanged() method.

And for the CustomListAdapter:

public class CustomListAdaper extends BaseAdapter {

    protected List<CustomListElement> elementList;

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        super.registerDataSetObserver(observer);

        for (CustomListElement element : elementList)
            element.registerDataSetObserver(observer);
    }
}

I.e. the observers are "handed through".

Now, when invoking

setListAdapter(new CustomListAdapter(customElementList));

within a ListActivity this should register an android.widget.AbsListView.AdapterDataSetObserver within the setAdapter method of ListView (invoked from setListAdapter of ListActivity).

Upon notifying the registered DataSetObserver objects of any change the onChanged method of the AdapterDataSetObserver and therefor requestLayout of the ListView should be invoked. This should (to my understanding) refresh the ListView.

However, the ListView is not updated with the new data.

I realize it has been pointed out that notifyDataSetChanged and (maybe) notifyChanged should be run within a runOnUiThread environment, however that does not seem to fix the issue.

I also realize that similar questions came up, but not with this specific set of android classes, and with unsatisfying answers.

Am i missing anything? Any insight into why this breaks and how to fix it is greatly appreciated.

like image 647
Hauke Avatar asked Dec 07 '10 11:12

Hauke


3 Answers

The registerDataSetObserver() part of the Adapter interface is for any external objects who might be interested to know when the data set changes. A ListView shouldn't really be interested in these methods... if it's BaseAdapter content changes, you call BaseAdapter.notifyDataSetChanged() which will tell the ListView to update itself.

In other words you only need to make the following tiny change:

public void setValue(Object newValue) {
     this.value = newValue;
     notifyDataSetChanged();
}

Actually, since you're changing the state of an existing item (rather than adding new ones etc) then notifyDataSetInvalidated() would be a better choice.

And of course you don't need any of that DataSetObserver stuff unless you actually do have other objects elsewhere that need to know about this data.

like image 130
Reuben Scratton Avatar answered Oct 13 '22 04:10

Reuben Scratton


The issue is resolved. The problem was in fact at a different point (an intermediate class that was not mentioned here didn't react appropriately to changes). The initial code works beautifully.

Thanks alot for the effort,

like image 43
Hauke Avatar answered Oct 13 '22 04:10

Hauke


adapter.notifyDataSetChanged();
like image 26
parthasarathy Avatar answered Oct 13 '22 04:10

parthasarathy