在构建期间在将小部件作为参数传递时调用setstate()或markneedsbuild()

时间:2020-04-08 07:12:17

标签: flutter exception dart

我有一个带有某些按钮的Stateful Widget。每次按按钮时,我要显示不同类型的Dialog。我为Button创建了一个函数,对于每个按钮,我只需调用该函数即可。

由于要在不同的按钮上显示不同的Dialog,我尝试将Dialog Widget作为按钮函数的参数传递,并在{{1 }}。当我尝试构建应用程序时,它会显示这些错误。


onPressed



放置按钮小部件的类:

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building DialogPage(dirty, dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#e6799]], state: _DialogPageState#a5060):
setState() or markNeedsBuild() called during build.

This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets.  A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: Overlay-[LabeledGlobalKey<OverlayState>#8e4e3]
  state: OverlayState#665ea(entries: [OverlayEntry#1cc53(opaque: true; maintainState: false), OverlayEntry#020ad(opaque: false; maintainState: true), OverlayEntry#1d32e(opaque: false; maintainState: false), OverlayEntry#9a4ae(opaque: false; maintainState: true), OverlayEntry#2728f(opaque: false; maintainState: false), OverlayEntry#33d56(opaque: false; maintainState: true)])
The widget which was currently being built when the offending call was made was: DialogPage
  dirty
  dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#e6799]]
  state: _DialogPageState#a5060
The relevant error-causing widget was: 
  DialogPage file:///C:/Users/imsajib02/AndroidStudioProjects/Flutter/widgets/lib/main.dart:43:32
When the exception was thrown, this was the stack: 
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3896:11)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3911:6)
#2      State.setState (package:flutter/src/widgets/framework.dart:1168:14)
#3      OverlayState.insertAll (package:flutter/src/widgets/overlay.dart:344:5)
#4      OverlayRoute.install (package:flutter/src/widgets/routes.dart:44:24)
...
════════════════════════════════════════════════════════════════════════════════════════════════════

════════ (2) Exception caught by widgets library ═══════════════════════════════════════════════════
The method 'drive' was called on null.
Receiver: null
Tried calling: drive<Color>(Instance of '_ChainedEvaluation<Color>')
The relevant error-causing widget was: 
  MaterialApp file:///C:/Users/imsajib02/AndroidStudioProjects/Flutter/widgets/lib/main.dart:11:12
════════════════════════════════════════════════════════════════════════════════════════════════════

════════ (3) Exception caught by widgets library ═══════════════════════════════════════════════════
'package:flutter/src/animation/animations.dart': Failed assertion: line 376 pos 15: 'parent != null': is not true.
The relevant error-causing widget was: 
  MaterialApp file:///C:/Users/imsajib02/AndroidStudioProjects/Flutter/widgets/lib/main.dart:11:12
════════════════════════════════════════════════════════════════════════════════════════════════════
D/FlutterView( 3883): Detaching from a FlutterEngine: io.flutter.embedding.engine.FlutterEngine@e78ea39



我从中调用对话框小部件的类:

class DialogPage extends StatefulWidget {

  @override
  _DialogPageState createState() => _DialogPageState();
}

class _DialogPageState extends State<DialogPage> {

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text("Dialogs"),
      ),
      body: Center(
        child: SingleChildScrollView(
          padding: EdgeInsets.only(top: 35),

          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            verticalDirection: VerticalDirection.down,
            children: <Widget>[

              Button("DEFAULT DIALOG", DialogCollection().defaultDialog(context)),
              Button("DIALOG WITH ICON - 1", DialogCollection().customDialog_1(context)),
              Button("Widget", DialogCollection().defaultDialog(context)),
              Button("Widget", DialogCollection().defaultDialog(context)),
              Button("Widget", DialogCollection().defaultDialog(context)),
              Button("Widget", DialogCollection().defaultDialog(context)),
            ],
          ),
        ),
      ),
    );
  }


  Button(String text, Widget widget) {

    return Column(
      children: <Widget>[

        Container(
          width: 230,
          child: RaisedButton(
            onPressed: () {


            },
            shape: RoundedRectangleBorder(
              borderRadius: new BorderRadius.circular(25.0),
              //side: BorderSide(color: Colors.red)
            ),
            color: Colors.blueGrey,
            padding: EdgeInsets.only(top: 12.0, bottom: 12.0, left: 40.0, right: 40.0),
            textColor: Colors.white,
            child: Text(text, textAlign: TextAlign.center ,style: TextStyle(
              fontWeight: FontWeight.bold,
              fontSize: 18,
            ),
            ),
          ),
        ),

        Container(
          height: 35,
        )
      ],
    );
  }
}

1 个答案:

答案 0 :(得分:1)

您可以在下面复制粘贴运行完整代码
DialogCollection().defaultDialog(context)表示执行此功能
您可以使用Button调用DialogCollection().defaultDialog以传递函数地址并传递context

代码段

Button("DEFAULT DIALOG", DialogCollection().defaultDialog, context)

Button(String text, Function callback, BuildContext context) {
    return Column(
      children: <Widget>[
        Container(
          width: 230,
          child: RaisedButton(
            onPressed: () {
              callback(context);
            },

工作演示

enter image description here

完整代码

import 'package:flutter/material.dart';

class DialogCollection {
  defaultDialog(BuildContext context) {
    return showDialog(
        context: context,
        //barrierDismissible: false, //on touch outside does not dismiss the dialog
        builder: (BuildContext context) {
          return WillPopScope(
            //WillPopScope stops dismissing dialog on outside touch and back press
            onWillPop: () {
              Navigator.of(context).pop();
              return null;
            },
            child: AlertDialog(
              title: Text(
                "Dialog Title",
                textAlign: TextAlign.center,
              ),
              titlePadding: const EdgeInsets.all(15.0),
              titleTextStyle: TextStyle(
                color: Colors.redAccent,
                fontSize: 20,
                fontWeight: FontWeight.bold,
              ),
              content: Text("This is the description of the dialog."),
              actions: <Widget>[
                FlatButton(
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                  color: Colors.lightBlueAccent,
                  textColor: Colors.white,
                  child: Text(
                    "Yes",
                    style: TextStyle(
                      fontSize: 18,
                    ),
                  ),
                ),
                FlatButton(
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                  color: Colors.redAccent,
                  textColor: Colors.white,
                  child: Text(
                    "No",
                    style: TextStyle(
                      fontSize: 18,
                    ),
                  ),
                ),
              ],
            ),
          );
        });
  }
}

class DialogPage extends StatefulWidget {
  @override
  _DialogPageState createState() => _DialogPageState();
}

class _DialogPageState extends State<DialogPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Dialogs"),
      ),
      body: Center(
        child: SingleChildScrollView(
          padding: EdgeInsets.only(top: 35),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            verticalDirection: VerticalDirection.down,
            children: <Widget>[
              Button(
                  "DEFAULT DIALOG", DialogCollection().defaultDialog, context),
              //Button("DIALOG WITH ICON - 1", DialogCollection().customDialog_1(context)),
              /* Button("Widget", DialogCollection().defaultDialog(context)),
              Button("Widget", DialogCollection().defaultDialog(context)),
              Button("Widget", DialogCollection().defaultDialog(context)),
              Button("Widget", DialogCollection().defaultDialog(context)),*/
            ],
          ),
        ),
      ),
    );
  }

  Button(String text, Function callback, BuildContext context) {
    return Column(
      children: <Widget>[
        Container(
          width: 230,
          child: RaisedButton(
            onPressed: () {
              callback(context);
            },
            shape: RoundedRectangleBorder(
              borderRadius: new BorderRadius.circular(25.0),
              //side: BorderSide(color: Colors.red)
            ),
            color: Colors.blueGrey,
            padding: EdgeInsets.only(
                top: 12.0, bottom: 12.0, left: 40.0, right: 40.0),
            textColor: Colors.white,
            child: Text(
              text,
              textAlign: TextAlign.center,
              style: TextStyle(
                fontWeight: FontWeight.bold,
                fontSize: 18,
              ),
            ),
          ),
        ),
        Container(
          height: 35,
        )
      ],
    );
  }
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: DialogPage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}