Skip to content

ListView.builder builds unecessary items when using ScrollController #24791

Closed

Description

@shinayser

When calling the method "jumpTo" on the ScrollController, the ListView builds every item between the current position and the "scrollTo" position;

This code snippet shows the problem. In the log, it will print every item , from 0 to 10000, wich takes a loooong time to run and freezes the entire application.

The desired behavior should be the list building only the last elements of the list.

class TestListViewBuilder extends StatelessWidget {
  final _values = List.generate(10000, (index) => index);
  final _controller = ScrollController();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        RaisedButton(
          child: Text("Go to bottom"),
          onPressed: () {
            _controller.jumpTo(_controller.position.maxScrollExtent);
          },
        ),
        Expanded(
          child: ListView.builder(
            controller: _controller,
            itemBuilder: (context, index) {
              print("Building index $index");
              return ListTile(title: Text("Index $index"));
            },
            itemCount: _values.length,
          ),
        ),
      ],
    );
  }
}

Flutter doctor:

[√] Flutter (Channel unknown, v0.11.9, on Microsoft Windows [versão 10.0.17134.407], locale pt-BR)
[√] Android toolchain - develop for Android devices (Android SDK 28.0.3)
[√] Android Studio (version 3.2)
[√] IntelliJ IDEA Community Edition (version 2018.3)
[√] Connected device (1 available)

• No issues found!

Activity

  1. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    p: material_uimaterial_ui package in flutter/packages
    on Nov 28, 2018
  2. added this to the milestone on Nov 28, 2018
  3. added
    c: performanceRelates to speed or footprint issues (see "perf:" labels)
    f: scrollingViewports, list views, slivers, etc.
    on Nov 28, 2018
  4. zoechi commented on Nov 28, 2018

    @zoechi
    Contributor

    #21023 looks somewhat related.

  5. HansMuller commented on Nov 28, 2018

    @HansMuller
    Contributor

    The intermediate list items are built because ListView doesn't now how big they are; so to scroll to the end it needs to layout them all out, one at a time...

    You can avoid the problem by specifying itemExtent, which means that all of the items have the same height. In this case itemExtent: 56.0 should DTRT.

  6. shinayser commented on Nov 28, 2018

    @shinayser
    Author

    But some cases we can't specify the itemExtent, since the item itself has a dynamic height.
    Think for example in a log list: a lot of lines of text are being added to it each second. Some lines of text are bigger than others.

  7. HansMuller commented on Nov 28, 2018

    @HansMuller
    Contributor

    Specifying itemExtent is definitely optional and big lists that contain variable height items are not unusual.

    Interactively scrolling a large list of variable height items is efficient because it usually isn't necessary to realize and then discard a large number of items.

    Although programmatically scrolling to an arbitrary offset requires computing the size of all of the items between the current offset and the new one, scrolling to the end of a list for which itemCount is non-null could be made more efficient.

  8. shinayser commented on Nov 28, 2018

    @shinayser
    Author

    So, that mean that it is impossible to do it? There is not another workaround?

  9. HansMuller commented on Nov 28, 2018

    @HansMuller
    Contributor

    To display very large list of arbitrary sized items that supports scrolling to an arbitrary offset in something like constant time, you'd have to build a custom scrolling container that could take advantage of app-specific constraints that applied to the distribution of item sizes.

  10. zoechi commented on Nov 29, 2018

    @zoechi
    Contributor

    #12319 is about scrolling to an index

  11. veenatic82 commented on Sep 14, 2019

    @veenatic82

    I am even seeing this happen when you set a PageStorageKey to a CustomScrollView. Switch back to the same widget and when flutter tries to preserve the scroll position, it builds all the items from the beginning. So, if you had 5000 items in your ScrollView, and you are at 4998th one, for example, it is rebuilding all items from the beginning till 4998th item. Also, during that process, I am seeing an increased memory pressure, like its shoots memory usage from say 15mb to 400 mb and when you scroll up or down for some time, it comes back to normal. But I think on devices where memory is limited, you may see Out Of memory exception. I tested with very small items say 50 characters each. So, if you have images or more stuff on each item, surely memory can shoot event more.
    I think we need to have a solution for this. Any plans on fixing this?

  12. VladyslavBondarenko commented on Apr 2, 2020

    @VladyslavBondarenko

    Persists with dev v1.16.4-pre.33

  13. esDotDev commented on Apr 2, 2020

    @esDotDev

    To display very large list of arbitrary sized items that supports scrolling to an arbitrary offset in something like constant time, you'd have to build a custom scrolling container that could take advantage of app-specific constraints that applied to the distribution of item sizes.

    It feels like there is a middle ground here, a non app-specific method where the app-developer could aid the list in it's calculations... Anything to avoid doing a full build and layout pass on each element.

    Thinking something like a measure function we could provide.

    extentCalculator: (i) => return itemData[i].desc != null? 100 : 70;
    

    App developers could then come up with novel ways of calculating our expected heights, without the list needing to actually lay everything out, and without developers having to build a custom list.

    For example in the log example above, I could wrap my list in a LayoutBuilder, and then (using maxWidth, characterWidth, string.length and lineHeight, all of which are known to me) I could fairly easily calculate the height for each item (assuming monospace font)

    Note that this will become more and more of an issue, as Desktop and Web apps roll out, with scrollbars that use JumpTo constantly with very large delta's ( as opposed to finger scrolling which just naturally avoids this issue )

  14. added
    P2Important issues not at the top of the work list
    on May 29, 2020
  15. liyuqian commented on Jul 21, 2020

    @liyuqian
    Contributor

    This seems to be the same issue as #52207

  16. VladyslavBondarenko commented on Jul 27, 2020

    @VladyslavBondarenko

    Please follow up on #52207,
    closing current issue as duplicate,
    if you disagree please write in the comments and I will reopen it

  17. github-actions commented on Aug 14, 2021

    @github-actions

    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.

  18. locked as resolved and limited conversation to collaborators on Aug 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: performanceRelates to speed or footprint issues (see "perf:" labels)f: scrollingViewports, list views, slivers, etc.frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: material_uimaterial_ui package in flutter/packages

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions