Skip to content

Calling MultiChildLayoutDelegate.hasChild from MultiChildLayoutDelegate.getSize throws an exception because _idToChild is null #115898

@crazy-rodney

Description

@crazy-rodney

Steps to Reproduce

  1. Execute flutter run on the code sample
  2. Exception is thrown

Expected results: Calling hasChild in getSize returns normally.

Actual results: Calling hasChild in getSize throws an exception.

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

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomMultiChildLayout(
        delegate: _MultiChildLayoutDelegate(),
        children: [
          LayoutId(
            id: 0,
            child: const SizedBox(
              width: 50,
              height: 50,
            ),
          ),
          LayoutId(
            id: 1,
            child: const SizedBox(
              width: 50,
              height: 50,
            ),
          ),
          LayoutId(
            id: 2,
            child: const SizedBox(
              width: 50,
              height: 50,
            ),
          )
        ],
      ),
    );
  }
}

class _MultiChildLayoutDelegate extends MultiChildLayoutDelegate {
  _MultiChildLayoutDelegate();

  @override
  Size getSize(BoxConstraints constraints) {
    hasChild(0);
    return Size(constraints.maxWidth, constraints.maxHeight);
  }

  @override
  void performLayout(Size size) {}

  @override
  bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) {
    return true;
  }
}
Logs
           ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
           The following _CastError was thrown during performLayout():
           Null check operator used on a null value

           The relevant error-causing widget was:
             CustomMultiChildLayout
             CustomMultiChildLayout:file:///Users/max/AndroidStudioProjects/layout_bug_example/lib/main.dart:28:13

           When the exception was thrown, this was the stack:
           #0      MultiChildLayoutDelegate.hasChild (package:flutter/src/rendering/custom_layout.dart:133:46)
           #1      _MultiChildLayoutDelegate.getSize (package:layout_bug_example/main.dart:63:5)
           #2      RenderCustomMultiChildLayoutBox._getSize (package:flutter/src/rendering/custom_layout.dart:359:44)
           #3      RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:409:12)
           #4      RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7)
           #5      RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11)
           #6      MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:171:12)
           #7      _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:1055:7)
           #8      MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:240:7)
           #9      RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:410:14)
           #10     RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7)
.....
       The following RenderObject was being processed when the exception was fired: RenderCustomMultiChildLayoutBox#21a29 relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE:
             creator: CustomMultiChildLayout ← KeyedSubtree-[GlobalKey#19ad8] ← _BodyBuilder ← MediaQuery ←
               LayoutId-[<_ScaffoldSlot.body>] ← CustomMultiChildLayout ← _ActionsMarker ← Actions ←
               AnimatedBuilder ← DefaultTextStyle ← AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#ce20a ink
               renderer] ← ⋯
             parentData: offset=Offset(0.0, 0.0); id=_ScaffoldSlot.body (can use size)
             constraints: BoxConstraints(0.0<=w<=411.4, 0.0<=h<=843.4)
             size: MISSING
           This RenderObject had the following descendants (showing up to depth 5):
               child 1: RenderConstrainedBox#b765d NEEDS-LAYOUT NEEDS-PAINT
               child 2: RenderConstrainedBox#938bd NEEDS-LAYOUT NEEDS-PAINT
               child 3: RenderConstrainedBox#93540 NEEDS-LAYOUT NEEDS-PAINT
           ════════════════════════════════════════════════════════════════════════════════════════════════════

Running "flutter pub get" in layout_bug_example...                 253ms
Analyzing layout_bug_example...                                         
No issues found! (ran in 3.1s)
[✓] Flutter (Channel stable, 3.3.8, on macOS 13.0.1 22A400 darwin-arm, locale en-DE)
    • Flutter version 3.3.8 on channel stable at /Users/max/fvm/versions/3.3.8
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 52b3dc25f6 (2 weeks ago), 2022-11-09 12:09:26 +0800
    • Engine revision 857bd6b74c
    • Dart version 2.18.4
    • DevTools version 2.15.0

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/max/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: /Users/max/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/213.7172.25.2113.9123335/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
    • All Android licenses accepted.

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

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

[✓] Android Studio (version 2021.3)
    • Android Studio at /Users/max/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/213.7172.25.2113.9014738/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 11.0.13+0-b1751.21-8125866)

[✓] Android Studio (version 2021.3)
    • Android Studio at /Users/max/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/213.7172.25.2113.9123335/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 11.0.13+0-b1751.21-8125866)

[✓] IntelliJ IDEA Community Edition (version 2022.2.3)
    • IntelliJ at /Users/max/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/222.4345.14/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

[✓] Connected device (4 available)
    • Pixel 7 (mobile)            • 29021FDH2004TJ • android-arm64  • Android 13 (API 33)
    • sdk gphone64 arm64 (mobile) • emulator-5554  • android-arm64  • Android 12 (API 31) (emulator)
    • macOS (desktop)             • macos          • darwin-arm64   • macOS 13.0.1 22A400 darwin-arm
    • Chrome (web)                • chrome         • web-javascript • Google Chrome 107.0.5304.110

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

Not sure if I am not supposed to call hasChild during getSize. But since the documentation clearly states that this may be done

/// True if a non-null LayoutChild was provided for the specified id.
///
/// Call this from the [performLayout] or [getSize] methods to
/// determine which children are available, if the child list might
/// vary.
bool hasChild(Object childId) => _idToChild![childId] != null;

I assume this is either an issue with the documentation or with the framework.

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: layoutSystemChrome and Framework's Layout Issuesc: crashStack traces logged to the consoled: api docsIssues with https://api.flutter.dev/found in release: 3.3Found to occur in 3.3found in release: 3.6Found to occur in 3.6frameworkflutter/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 version

Type

No type

Projects

Status

Done (PR merged)

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions