Android: notifyDataSetChanged(); not working

梦想的初衷 提交于 2019-11-27 01:44:31

One of the main reasons notifyDataSetChanged() won't work for you - is,

Your adapter loses reference to your list.

When you first initialise the Adapter it takes a reference of your arrayList and passes it to its superclass. But if you reinitialise your existing arrayList it losses the reference, and hence, the communication channel with Adapter.

When creating and adding a new list to the Adapter. Always follow these guidelines:

  1. Initialise the arrayList while declaring it globally.
  2. Add the List to the adapter directly with out checking for null and empty values . Set the adapter to the list directly (don't check for any condition). Adapter guarantees you that wherever you make changes to the data of the arrayList it will take care of it, but never loose the reference.
  3. Always modify the data in the arrayList itself (if your data is completely new than you can call adapter.clear() and arrayList.clear() before actually adding data to the list) but don't set the adapter i.e If the new data is populated in the arrayList than just adapter.notifyDataSetChanged()

Stay true to the Documentation.

The thing you need to edit is put your

runOnUiThread(new Runnable() {
                public void run() {
                    /**
                     * Updating parsed JSON data into ListView
                     * */
                    adapter = new SimpleAdapter(
                            Monitorizacion.this, candidatosList,
                            R.layout.list_item, new String[] { TAG_NSERIE,
                                    TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA},
                            new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria});
                    setListAdapter(adapter);
                    adapter.notifyDataSetChanged();
                //  timer();
                }
            });

into the OnCreate(). and return the list candidatosList from Asynctask. than set timer for updating candidatosList list.

An adapter define the comportement of the layout ! -> setListAdapter() : Define the adapter for a ListView/GridView/Gallery... but you need to specify the data !

I recommend to you, to initialize 'setListAdapter' in the 'onCreate' or in the constructor. After you set the data into the adapter (exemple : adapter.setItem(yourData))

And NOW ! You should to call notifyDataSetChanged ! Because you have changed the data but the view isn't refresh and notifydatasetchanged() reload the content of the view (ListView/GridView/Gallery...)

For a good practice and understand correctly I recommend to you to use a 'custom adapter' using 'baseAdapter'

Read and do this tutorial (I haver learn with this): http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/

Read the documentation : http://developer.android.com/reference/android/widget/BaseAdapter.html

It might be worth checking if you have an empty override for registerDataSetObserver(). Android Studio added one for me without implementing the call to super. Adding it in as follows was enough to get my listView working again:

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

As Hissain describes above,

you need to maintain a reference to the list

Here's how I got it to work:

  1. Let the list being sent to the adapter be set as an instance member in the activity

  2. In the logic that performs a change to the data, make sure it updates the same list instance that the activity passed to the adapter

  3. Then calling .notifyDataSetChanged(); worked

Remember that listView position starts at 1, so you will have to do (listViewPosition - 1) for your your java.util.List

msangel

The update function should be called from UI thread. My answer is actually similar to @user1621629's answer with that difference that I am using rxJava, so here's working code that solve this problem for me:

this.subscriber = myAdapter.getSubscriber(); // keep for unsubscribe in destroy
dataSource.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(this.subscriber);

So I set all execution in order to get data for the list to computation thread, but showing result in UI thread.

Here's how I create subscriber for this:

public class MyListAdapter extends RecyclerView.Adapter<LocationListAdapter.ViewHolder> {


private List<ListItem> mDataset = new ArrayList<>();

public Subscriber<ListItem[]> getSubscriber() {
    return Subscribers.create(new Action1<ListItem[]>() {
        @Override
        public void call(ListItem[] listItems) {
            mDataset.clear();
            mDataset.addAll(Arrays.asList(listItems));
            notifyDataSetChanged();
        }
    });
}
......

I dont have much reputation to comment on Mr. Hissain answer.It is correct but I want to mention one more thing that reference to the list should not change. If data source underlying is changing, dont change the reference to new list. Actions only need to be done on the same list object. To do the same,clear the list using clear() and then add data to the same list using add() or addALL() and then call notifyDataSetChanged(). eg. On first initialization of the list

list = dataSource.getList();

then one can add and remove the content from the list and call notifyDataSetChanged() it works fine but if in the code, one tries to change the reference to the other object. Like

list = dataSource.getList();

where getList() returns the new list everytime, hence the reference changes to some other list object and calling notifyDataSetChnaged does not have impact on the list.But if getList() returns the same list object, it works fine.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!