在构建期间调用颤振 showdialog setState() 或 markNeedsBuild()

Posted

技术标签:

【中文标题】在构建期间调用颤振 showdialog setState() 或 markNeedsBuild()【英文标题】:flutter showdialog setState() or markNeedsBuild() called during build 【发布时间】:2021-02-14 13:56:57 【问题描述】:

我有一个流构建器,它读取一个 Firestore 数据库,然后据此做出反应。现在列出了我数据库中的一些信息,但是我想为数据库中出现的特定值添加一个弹出屏幕,当我添加一个 showdialog 函数时,它开始给我

    ════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
setState() or markNeedsBuild() called during build.

错误。我怎样才能解决这个问题?我的代码如下。提前致谢。

//This is the function causing errors.      
_showMaterialDialog (String type) 
        if(type=="win")
          gameResult = "You Win, Gratz!";
        else if(type=="lose")
          gameResult = "You Lose :(";
        
        print("buraya girdi");
        print(gameResult);
        showDialog(
            context: context,
            builder: (_) => AlertDialog(
              title: Text("Result"),
              content: Text(gameResult),
              actions: <Widget>[
                FlatButton(
                  child: Text('Close'),
                  onPressed: () 
                    //Navigator.of(context).pop();
                    Navigator.pushNamed(context, HomeScreen.id);
                  ,
                )
              ],
            ));
      
    
      @override
      Widget build(BuildContext context) 
        if(_error) 
          return Text('error-game', textDirection: TextDirection.ltr);
        
    
        // Show a loader until FlutterFire is initialized
        if (!_initialized) 
          return Text('Loading', textDirection: TextDirection.ltr);
        
        return StreamBuilder<DocumentSnapshot>(
          stream: userSnapshot,
          builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) 
            if (snapshot.hasError) 
              return Text('Something went wrong');
            
    
            if (snapshot.connectionState == ConnectionState.waiting) 
              return Text("Loading");
            
            if(snapshot.hasData)
              Map<String, dynamic> userDocument  = snapshot.data.data();
              print(collectionPath);
              print(docPath);
              print(snapshot.data);
              print(userDocument);
              gameResult = userDocument['status'];

//this is place function called

              if(gameResult =="win" || gameResult =="lose")
                return _showMaterialDialog(gameResult);
              


              kullanicisayilari = userDocument['atilansayi'];
              List<dynamic> kullanicisayilariDuz = [];
              List<dynamic> rakipsayilariDuz = [];
              List<dynamic> sonuclarDuz = [];
              for (var numbers in kullanicisayilari)
                var splittedNumber = numbers.split('|');
                kullanicisayilariDuz.add(splittedNumber[0]);
              
              rakipsayilari = userDocument['rakipsallama'];
              sonuc = userDocument['sonuc'];
              for (var sonuclar in sonuc)
                var splittedSonuc = sonuclar.split('|');
                sonuclarDuz.add(splittedSonuc[0]);
              
              for (var rakipsayi in rakipsayilari)
                var splittedRakipSayi = rakipsayi.split('|');
                rakipsayilariDuz.add(splittedRakipSayi[0]);
              
              print(myNumbers.decimals);
              return MaterialApp(
                home:Scaffold(
                  appBar: AppBar(
                    backgroundColor: Colors.amberAccent,
                    title: Text('Sayı Avı Oyun Ekranı'),
                  ),
                  body:Column(
                    children: <Widget>[
                      Expanded(
                        flex: 80,
                        child: Row(
                          children: <Widget>[
                            Expanded(
                              flex: 40,
                              child: Column(
                                children: <Widget>[
                                  for(var numbers in kullanicisayilariDuz)Text(numbers),
                                  ]
                              ),
                            ),
                            Expanded(
                              flex: 10,
                              child: Column(
                                  children: <Widget>[
                                    for(var numbers in sonuclarDuz)Text(numbers),
                                  ]
                              ),
                            ),
                            Expanded(
                              flex: 50,
                              child: Column(
                                children: <Widget>[
                                  for(var numbers in rakipsayilariDuz)Text(numbers),
                                ]
                              ),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        flex:10,
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            showDeleteNumbers(1,'numberimage1'),
                            showDeleteNumbers(2,'numberimage2'),
                            showDeleteNumbers(3,'numberimage3'),
                            showDeleteNumbers(4,'numberimage4'),
                            Expanded(
                              child:FlatButton(
                                onPressed: ()
                                  sendnumber();
                                ,
                                child: Image.asset('images/send.png'),
                              ),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        flex: 10,
                        child: Row(
                          children: <Widget>[
                            attachNumber('1','one.png'),
                            attachNumber('2','two.png'),
                            attachNumber('3','three.png'),
                            attachNumber('4','four.png'),
                            attachNumber('5','five.png'),
                            attachNumber('6','six.png'),
                            attachNumber('7','seven.png'),
                            attachNumber('8','eight.png'),
                            attachNumber('9','nine.png'),
                            attachNumber('0','zero.png'),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              );
            
          ,
        );
      

    

【问题讨论】:

【参考方案1】:

如果您不确定小部件是否仍在构建中,您始终可以使用以下解决方案:

SchedulerBinding.instance!.addPostFrameCallback((_) 
  //your dialog
);

【讨论】:

【参考方案2】:

可能是因为您在 if(snapshot.hasData) 下再次返回 MaterialApp。尝试删除 MaterialApp 并保留 Scaffold 中的代码。

【讨论】:

【参考方案3】:

经过一番研究,我了解到问题正在发生,因为函数小部件构建会导致问题,因为已经发生了构建事件,所以我创建了函数 asycn,它现在正在工作。

代码如下:

  _showMaterialDialog(String type) async
    if(type=="win")
      gameResult = "You Win, Gratz!";
    else if(type=="lose")
      gameResult = "You Lose :(";
    
    print("buraya girdi");
    print(gameResult);
    await Future.delayed(Duration(milliseconds: 50));
    showDialog (
        context: context,
        builder: (_) => AlertDialog(
          title: Text("Result"),
          content: Text(gameResult),
          actions: <Widget>[
            FlatButton(
              child: Text('Close'),
              onPressed: () 
                  Navigator.pushNamed(context, HomeScreen.id);
              ,
            )
          ],
        ));
  

【讨论】:

以上是关于在构建期间调用颤振 showdialog setState() 或 markNeedsBuild()的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:在构建错误期间调用了 setState() 或 markNeedsBuild()

颤振应用程序中的“setState() 或 MarkNeedsBuild() 期间调用”错误

颤振 - 如何在弹出窗口中创建表单

颤振:如何在应用程序开始之前显示对话框?

(在构建时出现错误)在构建期间调用 setState() 或 markNeedsBuild()。相关的导致错误的小部件是 MaterialApp

颤振构建运行器不起作用 - 调用了 getter 'uri' 为 null