Skip to content

Nested Adapter - Bad performance when having many items (gets laggy) #1279

@SwiftedMind

Description

@SwiftedMind

Hey,

I'm using the nested adapter approach to have horizontally scrolling collectionViews inside a vertically scrolling collectionView (just like in the nested adapter example).

The approach works fine when you only have a few cells inside the horizontal collectionViews. When I tried having about 500+ items, it starts to stutter every time a new row is being displayed. The scrolling stops for a few milliseconds and then goes on. I created a demo project to showcase this (I exaggerated the amount of items to make it clearer):

https://github.com/d3mueller/NestedAdapterTest

giphy

I looked into it and it looks like the problem is here (in the section controller that's holding the nested list adapter):

override func cellForItem(at index: Int) -> UICollectionViewCell {
        if let cell = collectionContext!.dequeueReusableCell(of:  NestedCell.self, for: self, at: index) as?  NestedCell {
            
            // This call takes a long time (sometimes a few dozen or hundred milliseconds)
            listAdapter.collectionView = cell.collectionView
            
            return cell
        }
        fatalError()
    }

The listAdapter.collectionView property has a setter method that runs every time the cell is being displayed. And something inside there takes a very long time. And that is causing problems while scrolling.
I guess this setter has to access all items from the data source (maybe to get the contentSize for the collectionView?), which takes some time for big arrays.

Having thousands of items is no problem for a single collectionView, it's still incredibly smooth. But when you have these nested adapters, vertical scrolling is quite laggy for many items per row.

Is there any way to improve the performance of this? Can I maybe cache some things to make setting listAdapter.collectionView faster? If yes, how would I do that?

If that's not possible, I would have to reduce the amount of items per row. I thought about dynamically loading new items as you scroll (while also deleting items you have long scrolled past). (Also, I load the data locally using CoreData, I don't have to download them or anything). That kind of works, but it has a big problem:

Using the ideas from #242, I'm trying to maintain the contentOffset while removing items at the beginning of the collectionView. It works, but after setting the contentOffset, every active scrolling animation is stopped, so there's no way to smoothly scroll through the cells. It stops every time new data is being loaded. I implemented this in the demo project. It's commented out

I've been trying to figure this out for the past week or so, I can't think of any solutions to this :D.
I'm thankful for any thoughts/ideas you might have. Thanks!

General information

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions