Skip to content

markNeedsBuild fails assertion with conditional Drawer #42580

@nbros

Description

@nbros

I have a Drawer that is only enabled on the root page, using this code:

drawer: Navigator.of(context).canPop() ? null : Drawer(child: SettingsDrawer()),

When I modify a "dark mode" setting in the drawer that causes a rebuild, I get the following error:

════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown while finalizing the widget tree:
setState() or markNeedsBuild() called when widget tree was locked.

This Scaffold widget cannot be marked as needing to build because the framework is locked.
The widget on which setState() or markNeedsBuild() was called was: Scaffold
    dependencies: [_InheritedTheme, MediaQuery, _LocalizationsScope-[GlobalKey#a243d], Directionality]
    state: ScaffoldState#e99f6(tickers: tracking 2 tickers)
When the exception was thrown, this was the stack
#0      Element.markNeedsBuild.<anonymous closure> 
package:flutter/…/widgets/framework.dart:3692
#1      Element.markNeedsBuild 
package:flutter/…/widgets/framework.dart:3702
#2      State.setState 
package:flutter/…/widgets/framework.dart:1161
#3      ScaffoldState._drawerOpenedCallback 
package:flutter/…/material/scaffold.dart:1399
#4      DrawerControllerState.close 
package:flutter/…/material/drawer.dart:405
...
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by animation library ═════════════════════════════════
'package:flutter/src/widgets/framework.dart': Failed assertion: line 3658 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
════════════════════════════════════════════════════════════════════════════════

In order to reproduce the issue, open the Drawer and tap the Dark Mode switch with the following (simplified) sample app:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

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

class Prefs extends ChangeNotifier {
  bool _darkMode = false;
  bool get darkMode => _darkMode;
  set darkMode(bool newValue) {
    if (newValue == _darkMode) return;
    _darkMode = newValue;
    notifyListeners();
  }
}

class AppConfig extends StatefulWidget {
  _AppConfigState createState() => _AppConfigState();
}

class _AppConfigState extends State<AppConfig> {
  final Prefs prefs = Prefs();

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<Prefs>.value(value: prefs, child: MyApp());
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final prefs = Provider.of<Prefs>(context);
    return MaterialApp(
      title: 'Test',
      theme: ThemeData(brightness: prefs.darkMode ? Brightness.dark : Brightness.light, primarySwatch: Colors.blue),
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("test")),
      drawer: Navigator.of(context).canPop() ? null : Drawer(child: SettingsDrawer()),
      body: Container(),
    );
  }
}

class SettingsDrawer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final prefs = Provider.of<Prefs>(context);
    return Scaffold(
      body: ListView(
        padding: EdgeInsets.zero,
        children: <Widget>[
          DrawerHeader(
            child: Text('Settings'),
            decoration: BoxDecoration(
              color: Colors.blue,
            ),
          ),
          ListTile(
            leading: Text("Dark Mode"),
            title: Switch(
              value: prefs.darkMode,
              onChanged: (value) => prefs.darkMode = value,
            ),
          ),
        ],
      ),
    );
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    c: crashStack traces logged to the consolef: material designflutter/packages/flutter/material repository.found in release: 1.22Found to occur in 1.22found in release: 1.26Found to occur in 1.26frameworkflutter/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

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions