flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
166.31k stars 27.52k forks source link

Add a lazy SliverTree #114299

Closed naamapps closed 5 months ago

naamapps commented 2 years ago

📜 Design Document


Related:

Use case

Currently when trying to implement tree UIs (for example: comments section with nested comments - see Instagram's comments for reference) there is no way to do it but to flatten the list and use one SliverList to show the data in the UI.

Proposal

Add a way to add a SliverList inside of a SliverList. This will allow the CustomListView to scroll with all the data while also perform nicely with all the Slivers benefits.

In my use case, this is critical in SliverAnimatedList.

If you have any other solutions I will be happy to discuss.

Solutions I tried

  1. Using a ListView.Builder inside the SliverList builder function with shrinkWrap: true. - Poor Performance
  2. As pointed above - Normalizing the nested list with the list.expand function and using this list as the data source. - Poor Developer Experience - because everytime new data arrives we need to manage the flattened list which is not ideal.

Code example

CustomScrollView(
    slivers: [
      SliverList(
        delegate: SliverChildBuilderDelegate(
          (context, index) {
            final data = widget.comments[index];
            return SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, index) {
                  if (index == 0) {
                    return CommentWidget(data);
                  } else {
                    return CommentWidget(
                        data.comments[index - 1],
                        isNested: true);
                  }
                },
                childCount: data.comments.length + 1,
              ),
            );
          },
          childCount: widget.comments.length,
        ),
      ),
    ]
)
jonahwilliams commented 2 years ago

Not quite SliverList, but this would be called something like SliverGroup. I don't believe we've writen it yet. FYI @Piinks if we have a bug for this already

naamapps commented 2 years ago

Thanks for the quick response @jonahwilliams, Just to clarify, we need a widget that gets a builder function in order to get the most performence out of this feature. Adding a widget that gets a children array is not quite helpful here since we can have plenty of nested items.

Piinks commented 2 years ago

I think there are a lot of options here, and lot of work currently in progress that will help this scenario.

Adding a widget that gets a children array is not quite helpful here since we can have plenty of nested items.

@jonahwilliams is right, a SliverGroup would be good here, if the contents of the SliverGroup are lazy loading, then the entire group will be lazy loading. We're planning on implementing this in the near future, it is being tracked in https://github.com/flutter/flutter/issues/33137 cc @thkim1011

However, it sounds like having a Tree builder widget would be more appropriate for this use case - and I am actually working on one right now. 😄 I am adding this issue into the 2D scrolling project for tracking so that I remember to come back and report on the design as it is coming along. There are other related issues there that you may be interested in where folks have shared their own solutions, packages and such while we get closer to finishing the tree widget.

SliverList supports box children, and while I don't know what it would look like to support boxes and/or sliver children, it may unnecessarily complicate the API, especially if we have new features on the way that will better support this use case.

naamapps commented 2 years ago

Thanks @Piinks for the detailed information.

I think that SliverList supporting both box and slivers as children actually simplifies the API, don't you think? It is more friendly for new flutter devs and also more intuitive in my opinion..

I prefer building my own solutions than using a widget with limited customizations. I have set in my project an infra for scrolling (with plenty of customization - animations, states and more) and it would really complicate the code to add a new widget..

That is why I suggested to nest a SliverList inside a SliverList, just because it is logical and also easy to use and understand as a developer.

Nevertheless, I look forward to see your solutions! Hope to hear from you soon, Thanks

zhujiageng commented 1 year ago

any update on this? it can help solve many performance issues.

flutter-triage-bot[bot] commented 7 months ago

This issue is assigned to @Piinks but has had no recent status updates. Please consider unassigning this issue if it is not going to be addressed in the near future. This allows people to have a clearer picture of what work is actually planned. Thanks!

github-actions[bot] commented 4 months ago

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.