Skip to content

RenderSliverMainAxisGroup causes lazy children to build eagerly #142183

Closed

Description

@olavemil

Steps to reproduce

Add a CustomScrollView with SliverMainAxisGroups with SliverLists or SliverGrids inside. Add a simple print in the lists' item builders to print the list and item indices. Rather only the visible and first item, all or most children are instantiated during the first layout pass, even for groups far below the visible extent.

For the minimal example below, the consequences are less severe, with only 10 or so built per group, but with several groups each with a sticky SliverPersistentHeader and a SliverGrid of images to be fetched for each child, there is a quite significant performance hit (and no way to keep all those images in memory at the same time).

My investigation led me to a missing cacheExtent update in the RenderSliverMainAxisGroup's performLayout, causing it to consume no cache extent, even though it's children would. As the layout progresses, each RenderSliverMainAxisGroup has the same cacheExtent set, as it is never decreased in between.

Adding the following at the end of performLayout, in sliver_group.dart line 287, seems to fix it for me:

    final double paintExtent = calculatePaintOffset(
      constraints,
      from: math.min(constraints.scrollOffset, 0),
      to: totalScrollExtent,
    );
    geometry = SliverGeometry(
      scrollExtent: totalScrollExtent,
      paintExtent: paintExtent,
      cacheExtent: paintExtent,
      maxPaintExtent: maxPaintExtent,
      hasVisualOverflow: totalScrollExtent > constraints.remainingPaintExtent ||
          constraints.scrollOffset > 0.0,
    );
}

Expected results

The children of any lists in view, and the first child for any subsequent lists should be built and laid out (for calculating max extent etc).

Actual results

All (or several) children for each list gets built immediately, regardless of whether the children or even lists are visible.

Code sample

Code sample
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const NonLazySliverGrids(),
    );
  }
}

class NonLazySliverGrids extends StatelessWidget {
  const NonLazySliverGrids({super.key});

  @override
  Widget build(BuildContext context) => CustomScrollView(
        slivers: [
          for (var i = 0; i < 100; i++)
            SliverMainAxisGroup(
              slivers: [
                SliverList.builder(
                  itemCount: 100,
                  itemBuilder: (context, index) {
                    print('list $i, item $index');
                    return Container(
                      height: 24,
                      color: Colors.primaries[index % Colors.primaries.length],
                    );
                  },
                ),
              ],
            ),
        ],
      );
}

Screenshots or Video

No response

Logs

No response

Flutter Doctor output

Doctor output
[√] Flutter (Channel stable, 3.16.8, on Microsoft Windows [Version 10.0.22631.3007], locale en-US)
    • Flutter version 3.16.8 on channel stable at C:\src\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 67457e669f (8 days ago), 2024-01-16 16:22:29 -0800
    • Engine revision 6e2ea58a5c
    • Dart version 3.2.5
    • DevTools version 2.28.5

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at C:\Users\~\AppData\Local\Android\sdk
    • Platform android-34, build-tools 34.0.0
    • Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-b2043.56-10550314)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop Windows apps (Visual Studio Build Tools 2022 17.7.6)
    • Visual Studio at C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools
    • Visual Studio Build Tools 2022 version 17.7.34221.43
    • Windows 10 SDK version 10.0.22621.0

[√] Android Studio (version 2023.1)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-b2043.56-10550314)

[√] VS Code (version 1.85.2)
    • VS Code at C:\Users\~\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.80.0

[√] Connected device (3 available)
    • Windows (desktop) • windows • windows-x64    • Microsoft Windows [Version 10.0.22631.3007]
    • Chrome (web)      • chrome  • web-javascript • Google Chrome 120.0.6099.225
    • Edge (web)        • edge    • web-javascript • Microsoft Edge 120.0.2210.144

[√] Network resources
    • All expected network resources are available.

• No issues found!

Activity

  1. added
    in triagePresently being triaged by the triage team
    on Jan 25, 2024
  2. huycozy commented on Jan 25, 2024

    @huycozy
    Member

    Thanks for the report. I can see all SliverList's items are instantiated on all SliverMainAxisGroup(s). Attaching a recorded video and updated sample code to see the issue more clearly.

    Screen.Recording.2024-01-25.at.16.52.02.mp4
    Sample code
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          debugShowCheckedModeBanner: false,
          home: NonLazySliverGrids(),
        );
      }
    }
    
    class NonLazySliverGrids extends StatelessWidget {
      const NonLazySliverGrids({super.key});
    
      @override
      Widget build(BuildContext context) => CustomScrollView(
            slivers: [
              for (var i = 0; i < 100; i++)
                SliverMainAxisGroup(
                  slivers: [
                    SliverList.builder(
                      itemCount: 100,
                      itemBuilder: (context, index) {
                        print('list $i, item $index');
                        return Container(
                          alignment: Alignment.center,
                          height: 24,
                          color: Colors.primaries[index % Colors.primaries.length],
                          child: Text(
                            'list $i, item $index',
                            style: const TextStyle(
                              fontSize: 10,
                              color: Colors.white,
                            ),
                          ),
                        );
                      },
                    ),
                  ],
                ),
            ],
          );
    }
    
    flutter doctor -v (stable and master)
    [✓] Flutter (Channel stable, 3.16.8, on macOS 14.1 23B74 darwin-x64, locale en-VN)
        • Flutter version 3.16.8 on channel stable at /Users/huynq/Documents/GitHub/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 67457e669f (27 hours ago), 2024-01-16 16:22:29 -0800
        • Engine revision 6e2ea58a5c
        • Dart version 3.2.5
        • DevTools version 2.28.5
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
        • Android SDK at /Users/huynq/Library/Android/sdk
        • Platform android-34, build-tools 34.0.0
        • ANDROID_HOME = /Users/huynq/Library/Android/sdk
        • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
        • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 15.0.1)
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Build 15A507
        • CocoaPods version 1.14.3
    
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Android Studio (version 2023.1)
        • Android Studio at /Applications/Android Studio Hedgehog.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)
    
    [✓] Android Studio (version 2022.2)
        • Android Studio at /Applications/Android Studio.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • android-studio-dir = /Applications/Android Studio.app/
        • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
    
    [✓] VS Code (version 1.85.1)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.80.0
    
    [✓] Connected device (3 available)
        • iPhone (mobile) • d9a94afe2b649fef56ba0bfeb052f0f2a7dae95e • ios            • iOS 15.8 19H370
        • macOS (desktop) • macos                                    • darwin-x64     • macOS 14.1 23B74 darwin-x64
        • Chrome (web)    • chrome                                   • web-javascript • Google Chrome 120.0.6099.234
    
    [✓] Network resources
        • All expected network resources are available.
    
    • No issues found!
    [!] Flutter (Channel master, 3.19.0-9.0.pre.139, on macOS 14.1 23B74 darwin-x64, locale en-VN)
        • Flutter version 3.19.0-9.0.pre.139 on channel master at /Users/huynq/Documents/GitHub/flutter_master
        ! Warning: `flutter` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/flutter, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path.
        ! Warning: `dart` on your path resolves to /Users/huynq/Documents/GitHub/flutter/bin/dart, which is not inside your current Flutter SDK checkout at /Users/huynq/Documents/GitHub/flutter_master. Consider adding /Users/huynq/Documents/GitHub/flutter_master/bin to the front of your path.
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 703e12f524 (83 minutes ago), 2024-01-24 17:49:08 -0800
        • Engine revision 4880592ca5
        • Dart version 3.4.0 (build 3.4.0-69.0.dev)
        • DevTools version 2.31.0
        • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
        • Android SDK at /Users/huynq/Library/Android/sdk
        • Platform android-34, build-tools 34.0.0
        • ANDROID_HOME = /Users/huynq/Library/Android/sdk
        • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
        • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 15.0.1)
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Build 15A507
        • CocoaPods version 1.14.3
    
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Android Studio (version 2023.1)
        • Android Studio at /Applications/Android Studio Hedgehog.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)
    
    [✓] Android Studio (version 2022.2)
        • Android Studio at /Applications/Android Studio.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • android-studio-dir = /Applications/Android Studio.app/
        • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
    
    [✓] VS Code (version 1.85.2)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.80.0
    
    [✓] Connected device (4 available)
        • RMX2001 (mobile) • EUYTFEUSQSRGDA6D                         • android-arm64  • Android 11 (API 30)
        • iPhone (mobile)  • d9a94afe2b649fef56ba0bfeb052f0f2a7dae95e • ios            • iOS 15.8 19H370
        • macOS (desktop)  • macos                                    • darwin-x64     • macOS 14.1 23B74 darwin-x64
        • Chrome (web)     • chrome                                   • web-javascript • Google Chrome 120.0.6099.234
    
    [✓] Network resources
        • All expected network resources are available.
    
    ! Doctor found issues in 1 category.
  3. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    f: scrollingViewports, list views, slivers, etc.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    and removed
    in triagePresently being triaged by the triage team
    on Jan 25, 2024
  4. self-assigned this
    on Jan 29, 2024
  5. added
    r: fixedIssue is closed as already fixed in a newer version
    on Jan 31, 2024
  6. github-actions commented on Feb 14, 2024

    @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.

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

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listf: scrollingViewports, list views, slivers, etc.found in release: 3.16Found to occur in 3.16found in release: 3.19Found to occur in 3.19frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework teamwaiting for PR to land (fixed)A fix is in flight

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions