Skip to content

Memory Leak: _DraggableScrollableSheetState doesn't dispose _DraggableSheetExtent #134209

@ksokolovskyi

Description

@ksokolovskyi

Is there an existing issue for this?

Steps to reproduce

_DraggableScrollableSheetState doesn't dispose _DraggableSheetExtent when DraggableScrollableController is not provided.

  1. _DraggableScrollableSheetState creates _DraggableSheetExtent:

    class _DraggableScrollableSheetState extends State<DraggableScrollableSheet> {
    late _DraggableScrollableSheetScrollController _scrollController;
    late _DraggableSheetExtent _extent;
    @override
    void initState() {
    super.initState();
    _extent = _DraggableSheetExtent(
    minSize: widget.minChildSize,
    maxSize: widget.maxChildSize,
    snap: widget.snap,
    snapSizes: _impliedSnapSizes(),
    snapAnimationDuration: widget.snapAnimationDuration,
    initialSize: widget.initialChildSize,
    shouldCloseOnMinExtent: widget.shouldCloseOnMinExtent,
    );
    _scrollController = _DraggableScrollableSheetScrollController(extent: _extent);
    widget.controller?._attach(_scrollController);
    }

    void _replaceExtent(covariant DraggableScrollableSheet oldWidget) {
    final _DraggableSheetExtent previousExtent = _extent;
    _extent = previousExtent.copyWith(
    minSize: widget.minChildSize,
    maxSize: widget.maxChildSize,
    snap: widget.snap,
    snapSizes: _impliedSnapSizes(),
    snapAnimationDuration: widget.snapAnimationDuration,
    initialSize: widget.initialChildSize,
    );
    // Modify the existing scroll controller instead of replacing it so that
    // developers listening to the controller do not have to rebuild their listeners.
    _scrollController.extent = _extent;
    // If an external facing controller was provided, let it know that the
    // extent has been replaced.
    widget.controller?._onExtentReplaced(previousExtent);
    previousExtent.dispose();
    if (widget.snap

  2. _DraggableScrollableSheetState delegates disposal of _DraggableSheetExtent to the DraggableScrollableController. But if DraggableScrollableController is not provided by the widget, the _DraggableSheetExtent won't be disposed:

    @override
    void dispose() {
    widget.controller?._detach(disposeExtent: true);
    _scrollController.dispose();
    super.dispose();
    }

Expected results

_DraggableScrollableSheetState disposes _DraggableSheetExtent when DraggableScrollableController is not provided.

Actual results

_DraggableScrollableSheetState doesn't dispose _DraggableSheetExtent when DraggableScrollableController is not provided.

Code sample

Test which reveals the leak:
testWidgetsWithLeakTracking('_DraggableScrollableSheetState leak', (WidgetTester tester) async {
  await tester.pumpWidget(
    Directionality(
      textDirection: TextDirection.ltr,
      child: MediaQuery(
        data: const MediaQueryData(),
        child: Align(
          alignment: Alignment.bottomCenter,
          child: DraggableScrollableSheet(
            builder: (BuildContext context, ScrollController scrollController) {
              return const Center();
            },
          ),
        ),
      ),
    ),
  );
}, leakTrackingTestConfig: LeakTrackingTestConfig.debugNotDisposed());

Flutter Doctor output

Doctor output
[✓] Flutter (Channel master, 3.14.0-14.0.pre.142, on macOS 13.0.1 22A400 darwin-arm64, locale en-GB)
    • Flutter version 3.14.0-14.0.pre.142 on channel master at /Users/ksokolovskyi/dev/flutter_master
    • Upstream repository [email protected]:ksokolovskyi/flutter.git
    • FLUTTER_GIT_URL = [email protected]:ksokolovskyi/flutter.git
    • Framework revision 3744050be3 (2 hours ago), 2023-09-07 05:27:18 -0400
    • Engine revision 5a45ecd24a
    • Dart version 3.2.0 (build 3.2.0-134.0.dev)
    • DevTools version 2.27.0

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
    • Android SDK at /Users/ksokolovskyi/Library/Android/sdk
    • Platform android-33, build-tools 33.0.1
    • ANDROID_HOME = /Users/ksokolovskyi/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.6b829.9-10027231)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14E300c
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.3)
    • 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
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)

[✓] IntelliJ IDEA Community Edition (version 2023.2)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • 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

[✓] VS Code (version 1.81.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.72.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 13.0.1 22A400 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 116.0.5845.140

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

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    a: tests"flutter test", flutter_test, or one of our testsfound in release: 3.14Found to occur in 3.14frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onteam-frameworkOwned by Framework team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions