setstate () или markneedsbuild () вызывается во время сборки при передаче виджета в качестве аргумента - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть Stateful Widget, в котором есть несколько кнопок. При каждом нажатии кнопки я хочу показать различные типы Dialog. Я сделал функцию для своей кнопки и для каждой кнопки просто вызываю эту функцию.

Поскольку я хочу показать другое Dialog при нажатии другой кнопки, я попытался передать Dialog Widget в качестве параметра функции кнопки и вызвать этот виджет внутри 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,
        )
      ],
    );
  }
}



класс, откуда я вызываю диалоговые виджеты:

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,
                  ),
                  ),
                ),
              ],
            ),
          );
        }
    );
  }
}

1 Ответ

1 голос
/ 08 апреля 2020

Вы можете скопировать и вставить полный код ниже
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),
      ),
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...