How to clear the views which are held in the ListView's RecycleBin?
Asked Answered
L

5

15

In Android's ListView widget, the ListView will hold the views which is got from getView method of an Adapter in a inner class RecycleBin.

How can I clear the views in the RecycleBin and force the ListView to recreate all the child views.

Lenis answered 21/8, 2012 at 6:8 Comment(3)
If you are using convertView, try to don't use it. You should inflate a layout and then return it as a View instance.Cursive
The sole purpose of using a ListView is to reuse child views. Why would you want to go against the current?Electrosurgery
I have got a method from you, thanks!Lenis
M
4

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.

Malachy answered 21/8, 2012 at 7:14 Comment(3)
Yes, I will use the convertView because of the potential oom issues. But in some exceptional case I need to change the type of listview's childview class, so I have to destroy all the views in recyclebin and call the getview method to recreate the childviews.Lenis
@zangtao In that case I think that a call to invalidate is what you need.Malachy
Calling invalidate or invalidateViews did not do the trick.Sahib
S
43

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 );
Sahib answered 28/4, 2013 at 9:43 Comment(5)
You're right setting the adapter does clear the recycler. As I said in my answer, I remember reading about invalidate() clearing the ListView(not 100% sure).Malachy
+1 That is indeed a neat trick, too bad that invalidate doesn't work here.Postoperative
Nice one, thanks. I needed this on Android 5.0, where the ripple effect on a recycled view was still animating after clicking on an item, even though the items in the adapter were replaced and the list was refreshed.Anglosaxon
The same thing applies to RecyclerView. Setting the same adapter will cause the Recycler to recreate all the views. I used this because the height of the views inside the Recycler changed.Serval
Android seriously pisses me off sometimes, there is no reason we should be sitting here trying all these options and failing.Manlike
M
4

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.

Malachy answered 21/8, 2012 at 7:14 Comment(3)
Yes, I will use the convertView because of the potential oom issues. But in some exceptional case I need to change the type of listview's childview class, so I have to destroy all the views in recyclebin and call the getview method to recreate the childviews.Lenis
@zangtao In that case I think that a call to invalidate is what you need.Malachy
Calling invalidate or invalidateViews did not do the trick.Sahib
T
3

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.

Tyrannize answered 15/1, 2015 at 8:20 Comment(1)
Thanks this is the only correct answer here. I was adjusting row height in ListView when item is clicked in ListView. Noticed views were accumalated in ListView recycle bin resulting in OOM eventually. reclaimViews() were the trick to wipe recycle bin. Avoiding convert view would also work, but that affects negatively in performance.Cocainism
C
1

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();
                        }
                    }
                });
Christi answered 8/2, 2018 at 14:59 Comment(1)
reclaimViews() is the key. also you need to first invalidateViews() then reclaimViews() or else you'll lose the scroll position.Cocainism
O
0

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.

Olid answered 21/8, 2012 at 6:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.