How do I check when my ListView has finished redrawing?
Asked Answered
V

3

13

I have a ListView. I updated its adapter, and call notifydatasetchanged(). I want to wait until the list finishes drawing and then call getLastVisiblePosition() on the list to check the last item.

Calling getLastVisiblePosition() right after notifydatasetchanged() doesn't work because the list hasnt finished drawing yet.

Volcano answered 20/3, 2015 at 18:37 Comment(2)
If you're updating the adapter contents, wouldn't you already know what's in the last item? Or do you really mean the last "visible" item?Archivolt
Ya the last visible item on the screenVolcano
J
48

Hopefully this can help:

  • Setup an addOnLayoutChangeListener on the listview
  • Call .notifyDataSetChanged();
  • This will fire off the OnLayoutChangeListener when completed
  • Remove the listener
  • Perform code on update (getLastVisiblePosition() in your case)

    mListView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
    
      @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        mListView.removeOnLayoutChangeListener(this);
        Log.e(TAG, "updated");
      }
    });
    
    mAdapter.notifyDataSetChanged();
    
Jeremiad answered 20/3, 2015 at 18:41 Comment(2)
It works but it is very slow on screen orientation change. Is there anyway to speed it up?Eelgrass
The speed issue is likely related to custom code firing off when calling .notifyDataSetChanged();Jeremiad
E
3

I think this implementation can solve the problem.

    // draw ListView in UI thread
    mListAdapter.notifyDataSetChanged();
    
    // enqueue a message to UI thread
    mListView.post(new Runnable() {
        @Override
        public void run() {
            // this will be called after drawing completed
        }
    });
Emblazonry answered 7/4, 2021 at 10:9 Comment(0)
L
0

You can implement callback, after the notifyDataSetChanged() it will be called and do the job you need. It means the data has been loaded to the adapter and at next draw cycle will be visible on the GUI. This mechanism is built-in in Android. See DataSetObserver.

Implement his callback and register it into the list adapter, don't forget to unregister it, whenevr you no longer need it.

/**
 * @see android.widget.ListAdapter#setAdapter(ListAdapter)
 */
@Override
public void setAdapter(android.widget.ListAdapter adapter) {
    super.setAdapter(adapter);

    adapter.registerDataSetObserver(new DataSetObserver() {
        @Override
        public void onChanged() {
            onListChanged();
            // ... or do something else here...
            super.onChanged();
        }
    });
}
Linctus answered 8/1, 2020 at 14:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.