In Android\'s ListView
widget, the ListView
will hold the views which is got from getView
method of an Adapter in a inner class
If I remember correctly a call to invalidate
on a ListView
widget will empty the cache of Views
which are currently stored. I would advise against emptying the cache of views of a ListView
because of the potential performance issues.
If you're not going to use the convertView
item then you'll end up with having to build the row view each time(resulting in a lot of objects constructed each time the user scrolls) + the extra memory occupied by the recycled views from the RecycleBin
which will never be used anyway.
There are a special method in ListView
- reclaimViews(List<View>)
. It moves all items that are currently in use and in recycle bin to specified list. Widget will request new views for items from Adapter
before rendering next time.
You can use reclaimed views, if there are not many changes to item structure, or scrap them completely. For example, i'm using this method to dynamically update background drawable for items when selection color was changed by user.
Calling invalidate() or invalidateViews() did not do the trick for me (as mentioned in the correct answer). The recycled views were still stored in the ListView. I had to dig in Android source code to find a solution. I checked many methods, including the setAdapter() method of the ListView class (Android API 15) :
@Override
public void setAdapter(ListAdapter adapter) {
// ...
mRecycler.clear();
// ...
}
As you noticed, setting an adapter clears the recycler, which holds all the recycled views in a list view. You do not have to create a new adapter, setting the same adapter is enough to clear the recycled views list in the list view :
Adapter adapter = listview.getAdapter ();
// ... Modify adapter ... do anything else you need to do
// To clear the recycled views list :
listview.setAdapter ( adapter );
In my opinion @nekavally offers the best solution. I have a ListView
and a SimpleCursorAdapter
. Sometimes I need to change the size of the list items. But since the adapter recycles the views, they may appear in the wrong way. So I'm just calling mListView.invalidateViews()
after reclaiming the recycled views, and it works just fine.
startAnimation(initialHeight, finalHeight, duration, new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
childView.getLayoutParams().height =
(Integer) animation.getAnimatedValue();
childView.requestLayout();
if (animation.getAnimatedFraction() == 1f) {
mListView.reclaimViews(new ArrayList<View>());
mListView.invalidateViews();
}
}
});
Remove object of recycle bin from ArrayList or the data structure you have used in your custom adapter and also call notifyDataSetChanged
method of your adapter.