recyclerlistview
recyclerlistview copied to clipboard
RecyclerView never removes items which is not visible in window
I have a thousands of data and when i scroll down i see that rowHasChanged
triggers on each item few times and close to end rowHasChanged
triggers more times that i have items, which is slow and i never see useEffect's callback which triggers when component did remove. So if i have a complex listItem RecyclerView consume a lot of memory. So that's a point to use recyclerView if it doesn't handle remove and recreate views which out of screen?
I solved this issue by tracking the index of the item that the users is seeing and saying on rowRender to render items that are x index below and y index above.
As it called RecyclerListView it must be done in library, and i as consumer must not thinking about it otherwise it is not a RecyclerListView it is basic listView without any performance optimizations.
@gustavolsilvano Hey gustavo, how did you achieved that?
I don't understand why this issue doesn't get more attention. This is the entire point of a component like this, and it doesn't do what it is supposed to do.
@peterzanetti and anyone else that encounters this issue for the future. I was able to resolve this issue by properly implementing the layout provider as the documentation does not do a proper job of explaining how the recycling works.
Essentially, the recycling depends on a proper layout provider implementation being able to determine dimensions and height/width for a given index item.
const layout_provider = useMemo(
() =>
new LayoutProvider(
(index) => 0, // This is very important for the recycling to work properly
(_, dimensions, index) => {
// The width is always full width
dimensions.width = SCREEN_WIDTH;
// Calculate the height based on the type
const item = data.current[index].item;
if (typeof item == 'string') {
dimensions.height = titleHeight;
} else {
dimensions.height = releaseHeight;
}
}
),
[SCREEN_WIDTH, titleHeight, releaseHeight]
);
In the snippet above, observe that the first argument to the LayoutProvider
aka. the getLayoutTypeForIndex
is simply a callback which always returns 0
aka. a fixed value. In my case, this was the problem which was causing the recycling to not work and the view to render / keep all items loaded.
My implementation before would simply return the index
itself for this callback which was causing the recycling to not work as the list view thought of each item as a different layout type
hence not recyclable. To be honest with you, I don't really know the purpose of having different types or when you would want to use different layout types, but in my case keeping it the same was the best way to go since I only had 2 types of items in my whole list and would return the appropriate dimensions depending on the type.