18

The documentation says that setItemViewCacheSize

sets the number of offscreen views to retain before adding them to the potentially shared recycled view pool.

and setMaxRecycledViews

sets the maximum number of ViewHolders to hold in the pool before discarding.

But don't they both function as a cache where views are taken from (i.e., the first sets the number of views cached by the RV, while the second sets that of the RVP)?

Also, when a view is needed, where is it taken first, from the RVP or from the RV's cache?

And what's the optimal (scrolling-wise, ignoring memory) configuration for the two for a simple unnested recyclerview?

Sid Go
  • 2,041
  • 3
  • 16
  • 29

2 Answers2

35

Here's the full documentation for setItemViewCacheSize():

Set the number of offscreen views to retain before adding them to the potentially shared recycled view pool.

The offscreen view cache stays aware of changes in the attached adapter, allowing a LayoutManager to reuse those views unmodified without needing to return to the adapter to rebind them.

In other words, when you scroll the RecyclerView such that there's a view that is just barely completely off-screen, the RecyclerView will keep it around so that you can scroll it back into view without having to re-execute onBindViewHolder().

This is different from the recycled view pool, which is a pool of views that the RecyclerView has said it doesn't need anymore, but which is kept around to avoid the expensive task of inflating new views.

In short, the "item view cache" holds elements in such a way that the RecyclerView can avoid calling both onCreateViewHolder() and onBindViewHolder(), whereas the recycled view pool holds elements such that the RecyclerView can avoid calling onCreateViewHolder() but will still have to call onBindViewHolder().

Also, when a view is needed, where is it taken first, from the RVP or from the RV's cache?

I don't think it really matters, and I don't know of a precise definition, but generally I think you can imagine that views that have just exited the device's viewport and then return to the viewport will be taken from the "item view cache", while views that come on-screen but were not previously on-screen will come from the recycled view pool.

And what's the optimal (scrolling-wise, ignoring memory) configuration for the two for a simple unnested recyclerview?

Just use the defaults. I would never consider changing these unless I had profiled my app and determined beyond a doubt that the defaults weren't working for me. But, if I just take you at your word, ignoring memory, the larger the cache size the better. But really, just use the defaults.

Community
  • 1
  • 1
Ben P.
  • 52,661
  • 6
  • 95
  • 123
  • 7
    What are the default values for both of those? – android developer Apr 12 '19 at 12:58
  • This is correct. I been banging my head around with `setItemViewCacheSize`. I do not get how the heck `onBindViewHolder` use to update the content is not getting called after adding new item but it displays the layout correctly. Then I realize that I modified the value of `setItemViewCacheSize` to 20. Setting it to zero fix the issue. – Mihae Kheel Sep 28 '19 at 14:16
  • 3
    In testing I found that the default item view cache size is **2**, and the default max recycled views is **5** _per view type_. – Trevor Feb 18 '21 at 04:29
  • I find the default values to be very small. This depends on you, but more likely than not, your views don't take that much memory and your device has relatively a ton of memory. So you can often safely increase these values quite a lot. – Trevor Jan 12 '22 at 07:48
23

I've read this article by Pavel Shmakov and it explains the difference between Pool and Cache

Pool and Cache in Action

  • If a ViewHolder was found nowhere, it is created and bound.
  • If a ViewHolder was found in pool, it is bound.
  • If a ViewHolder was found in cache, there is nothing to be done.

So, as long as the cache isn’t full, ViewHolders go there. If it’s full, a new ViewHolder pushes a ViewHolder from the “other end” of the cache into the pool. If a pool is already full, that ViewHolder is pushed into oblivion, to the garbage collector that is

Now let’s look at the way pool and cache behave in a couple of actual RecyclerView usage scenarios.

Consider scrolling: enter image description here

As we scroll downwards, there is a “tail” behind the currently seen items consisting of cached items and then a pooled item. When the item 8 appears on screen, no suitable ViewHolder is found in cache: no ViewHolder associated with position 8 there. So we use a pooled ViewHolder, which was previously at position 3. When item 6 disappears on top, it goes to the cache, pushing 4 into the pool.

The picture is different when we start scrolling in the opposite direction: enter image description here

Here we find a ViewHolder for position 5 in view cache and reuse it right away, without rebinding. And that seems to be the main use-case of the cache — to make scrolling in opposite direction, to the items we’ve just seen, more efficient. So if you have a news feed, the cache might be useless, since users won’t go back too often. But if it’s a list of things to choose from, say a gallery of wallpapers, you might want to extend the capacity of the cache.

Read more here https://android.jlelse.eu/anatomy-of-recyclerview-part-1-a-search-for-a-viewholder-404ba3453714

Joe Okatch
  • 660
  • 5
  • 9