【问题标题】:Flutter error: Each child must be laid out exactly once. On building layout颤振错误:每个孩子必须恰好布置一次。关于建筑布局
【发布时间】:2020-05-21 10:27:28
【问题描述】:

我正在使用flutter_bloc。

我有这样的代码:

class Settings extends StatelessWidget {
  final _formKey = GlobalKey<FormState>();
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
          title: new Text("SomeApp",style: TextStyle(color: Colors.white)),
          automaticallyImplyLeading: false,
          backgroundColor: myBlue.shade50,

          actions: <Widget>[
            IconButton(
              icon: new Icon(FontAwesomeIcons.download,color:  Colors.white),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => DownloadView()),
                );
              },
            ),
            IconButton(
              icon: new Icon(FontAwesomeIcons.chevronCircleLeft,color:  Colors.white),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => MainWindow()),
                );
              },
            ),]
      ),
      body: Container(
        padding: EdgeInsets.symmetric(vertical: 16),
        alignment: Alignment.center,
        child: new BlocBuilder<SettingsBloc, SettingsState>(
          builder: (context, state) {
            if (state is SettingsNotLoaded) {
              return new Center(
                  child: Text(
                    'count1',
                    style: TextStyle(fontSize: 24.0,color: Colors.black),
                  )
              );
            } else if (state is SettingsLoaded) {  
              return new Center(
                  child: Text(
                    'count2',
                    style: TextStyle(fontSize: 24.0,color: Colors.black),
                  )
              );
            }
            else
              {
                return new Center(
                    child: Text(
                      'count3',
                      style: TextStyle(fontSize: 24.0,color: Colors.black),
                    )
                );
              }
          },
        ),

      ),
    );
  }

当启动我的应用程序时,我看到了我想要的 appBar,但我没有看到正文中的任何文本(我应该看到 count1、count2 或 count3),但我得到了错误:

每个孩子都必须恰好布置一次。” 参考第 5 行 - return new Scaffold(

当然,我在 flutter_bloc 页面、https://flutter.dev/docs/development/ui/layout/tutorial、here 和 google 上查找了信息。

【问题讨论】:

  • 如果你先删除BlocBuilder会发生什么?
  • 如果我用 blocBuilder 删除整个 bloc 模式并只放置文本小部件一切正常
  • 对此有什么解决办法吗?它也发生在我身上
  • 你调试过看看state的值吗?新的是可选的

标签: android flutter flutter-layout flutter-bloc


【解决方案1】:

我也面临同样的问题。我做了以下事情:

  1. 从设备上卸载了应用程序
  2. 扑干净
  3. 颤动运行

【讨论】:

    【解决方案2】:

    这不是颤振的错误,我也遇到过同样的问题,虽然上面的解决方案是正确的,但有时似乎会失败。

    试试下面的命令

    flutter clean
    

    flutter pub get
    

    然后再次运行

    flutter run
    

    或者,如果您使用的是 Android Studio(启用了颤振插件)

    转到工具 > Flutter > Flutter Clean

    然后再次运行应用程序, 将执行与上述命令相同的操作

    在熟悉 Flutter 大约一周后,现在我明白了在代码中进行更改(例如在 pubspec.yaml 中添加新依赖项)需要停止应用程序并再次运行,我确实注意到 IDE 中的 GUI (我使用Android Studio)可能有一些问题,命令行中的上述命令可以正常工作。

    【讨论】:

      【解决方案3】:

      我只是遇到了同样的问题,我认为它只是颤振中的一个错误。停止并重新安装您的应用

      【讨论】:

        【解决方案4】:

        GetX 状态管理特定

        在我的例子中,我用 GetX 包装了一个小部件。我只是删除它并使用 Obx 来管理状态。

        【讨论】:

          【解决方案5】:

          在调试控制台中跟踪日志,在该错误下,您可能会看到一条日志:

          The stack when the error occurred was:
          .............
          .............
          .............
          

          仔细阅读这些行以了解问题所在!

          【讨论】:

          • 我需要给你打电话,你能给我任何社交媒体联系你吗?
          • 您可以通过 LinkedIn 与我联系:linkedin.com/in/ahmedatab 或通过电子邮件发送至:atab.ahmad98@gmail.com
          【解决方案6】:

          State 的构造函数中引用widget 时出现此错误:

          class MyWidget extends StatefulWidget {
            MyWidget(this.data, {Key? key}) : super(key: key);
          
            final String data;
          
            @override
            _MyWidgetState createState() => _MyWidgetState();
          }
          
          class _MyWidgetState extends State<MyWidget> {
            _MyWidgetState() {
              debugPrint(widget.data); // This line causes error.
            }
          
            @override
            Widget build(BuildContext context) {
              return Container();
            }
          }
          

          【讨论】:

            【解决方案7】:
            import 'package:flutter/material.dart';
            
            import 'package:font_awesome_flutter/font_awesome_flutter.dart';
            
            void main()=> runApp(BMIcalculatro());
            
            class BMIcalculatro extends StatelessWidget {
            
            @override
            
            Widget build(BuildContext context) {
            
            return MaterialApp(
            
            
            
              theme: ThemeData.dark().copyWith(
            
                primaryColor: Color(0xFF0A0E21),
            
            
                scaffoldBackgroundColor: Color(0xFF0A0E21),
            
              ),
            
              home: InputPage(),
            
            ) ;
            
            } }
            
            
            
            const activColor = Color(0xFF1D1E33);
            
            
            
            const inActiveColor = Color(0XFF111328);
            
            
            
            enum Gender{
            
            
            
            
            male, female
            
            
            
            }
            
            
            
            class InputPage extends StatefulWidget {
            
            
            
            
            @override
            
            
            
            _InputPageState createState() => _InputPageState();
            
            
            
            }
            
            
            
            class _InputPageState extends State {
            
            
            
            Gender genderSelected;
            
            
            
            @override
            
            
            
            Widget build(BuildContext context) {
            
            
            
            
            return Scaffold(
            
            
            
                appBar: AppBar(
            
            
            
                  title: Text('BMIcalculator'),
            
            
            
                  centerTitle: true,
            
            
            
                ),
            
                body: Column(
            
            
            
                  children: [
            
            
            
                    Expanded(
            
            
            
            
                      child: Row(
            
            
            
                        children: [
            
            
            
                          Expanded(
            
            
            
            
                            child: GestureDetector(
            
            
            
                              onTap: () {
            
            
            
                                setState(() {
            
            
            
                                  genderSelected=Gender.male;
            
            
            
                                });
            
            
            
            
                              },
            
            
            
                              child: ReusableCard(
            
            
            
            
            
                                colour: genderSelected ==Gender.male ? activColor: inActiveColor,
            
            
            
                                cardChaild: IconrContakt(
            
            
            
                                  icone: FontAwesomeIcons.mars,
            
            
            
                                  name: "MAIL",
            
            
            
                                ),
            
            
                              ),
            
                            ),
            
                          ),
            
                          Expanded(
            
            
            
                            child: GestureDetector(
            
            
            
                              onTap: () {
            
            
            
            
                                setState(() {
            
            
            
                                   genderSelected=Gender.female;
            
            
            
                                });
            
                              },
            
                              child: ReusableCard(
            
            
            
                                colour: genderSelected==Gender.female ? activColor:inActiveColor,
            
            
            
                                cardChaild: IconrContakt(
            
            
            
            
                                  icone: FontAwesomeIcons.venus,
            
            
            
                                  name: "female",
            
                                ),
            
                              ),
            
            
                            ),
            
            
                          ),
            
                        ],
            
                      ),
            
                    ),
            
                    Expanded(
            
            
            
                      child: Expanded(
            
            
            
                        child: ReusableCard(
            
            
            
                          colour: activColor,
            
            
                        ),
                      ),
            
                    ),
                    Expanded(
            
            
            
                      child: Row(
            
            
            
                        children: [
            
            
            
                          Expanded(
            
            
            
                              child: ReusableCard(
            
            
            
                            colour: activColor,
            
            
            
                          )),
            
                          Expanded(
            
            
            
                            child: ReusableCard(
            
            
            
                              colour: activColor,
            
            
            
                            ),
            
                          ),
            
                        ],
            
                      ),
            
                    ),
            
                    Container(
            
            
            
                      margin: EdgeInsets.only(top: 12),
            
            
            
                      decoration: BoxDecoration(
            
            
            
                        color: Color(0xFFEB1555),
            
            
            
                      ),
            
                      child: Center(
            
            
            
                          child: Text(
            
            
            
                        'BMI CALCULATOR',
            
            
            
                        style: TextStyle(color: Colors.white, fontSize: 20),
            
            
            
                      )),
            
                      width: double.infinity,
            
            
            
                      height: 80.0,
            
            
            
                    )
            
                  ],
            
                ),
            
                );
            
            } }
            
            
            
            class IconrContakt extends StatelessWidget {
            
            
            
            IconrContakt({this.icone, this.name});
            
            
            
            final IconData icone;
            
            
            
            final String name;
            
            
            
            @override
            
            
            
            Widget build(BuildContext context) {
            
            
            
            return Column(
            
            
            
              mainAxisAlignment: MainAxisAlignment.center,
            
            
            
              children: [
            
            
            
                Icon(
            
            
            
                  icone,
            
            
            
                  size: 80,
            
            
            
                ),
            
                SizedBox(
            
            
            
                  height: 15,
            
            
            
                ),
            
                Text(
            
            
            
                  name,
            
            
            
                  style: TextStyle(fontSize: 18.0),
            
            
            
                )
            
              ],
            
            );
            
            } }
            
            
            
            class ReusableCard extends StatelessWidget {
            
            
            
            ReusableCard({@required this.colour, this.cardChaild});
            
            
            
            final Color colour;
            
            
            
            final Widget cardChaild;
            
            
            
            @override
            
            
            
            Widget build(BuildContext context) {
            
            
            
            return Container(
            
            
            
              child: cardChaild,
            
            
            
              margin: EdgeInsets.all(12.0),
            
            
            
              decoration: BoxDecoration(
            
            
            
                color: colour,
            
            
            
                borderRadius: BorderRadius.circular(10.3),
            
            
            
              ),
            
            );
            
            } }
            

            这是错误

            ════════ 小部件库捕获的异常════════════════════════════════ ═

            'package:flutter/src/widgets/framework.dart':断言失败:第 5022 行 pos 16:>'child

            是!'

            ParentDataElement': 不正确。'

            相关的导致错误的小部件是 Scaffold lib\home.dart:23

            ════════════════════════════════════════════════ ═════════════════════════════════

            ════════渲染库捕获的异常═══════════════════════════════════ /p>

            每个孩子必须恰好布置一次。

            相关的导致错误的小部件是 Scaffold。

            【讨论】:

              【解决方案8】:

              在以下情况下可能会发生此错误:

              • 您使用 Navigator 2.0
              • 你使用ChildBackButtonDispatcher
              • 你热加载你的应用程序
              • 你忘了在build方法中优先:
              class _HomeState extends State<Home> {
                HomeRouterDelegate _routerDelegate;
                final _state = HomeState();
              
                ChildBackButtonDispatcher _backButtonDispatcher;
              
                @override
                void initState() {
                  super.initState();
                  _routerDelegate = HomeRouterDelegate(_state);
                }
              
                @override
                void didChangeDependencies() {
                  super.didChangeDependencies();
                  _backButtonDispatcher = Router.of(context)
                      .backButtonDispatcher
                      .createChildBackButtonDispatcher();
                }
              
                @override
                Widget build(BuildContext context) {
                  // The app will throw an exception 'Each child must be laid out exactly once.'
                  // without this line on each Hot Reload
                  // https://stackoverflow.com/a/66258147/1321917
                  _backButtonDispatcher.takePriority();
                  return Router(
                    routerDelegate: _routerDelegate,
                    backButtonDispatcher: _backButtonDispatcher,
                  );
                }
              }
              

              【讨论】:

                【解决方案9】:

                如何解决

                flutter clean
                

                虽然可以复制,但对我来说很好用

                在我的情况下是什么触发了它

                自从我在我的应用程序中实现 Streams 以来,这对我来说就开始了。

                我假设通过使用 StreamController 并更改曾经收听该流的内容,它会在运行时产生错误,并结合 StreamBuilder,我返回到 Widget

                重现错误的代码:

                  Widget passwordField(){
                    return StreamBuilder(
                      stream: bloc.getPasswordStream,
                        builder: (context,snapshot){
                          return TextField(
                            onChanged: bloc.addPasswordStream,
                            obscureText: true,
                            decoration: InputDecoration(
                                hintText: 'password',
                                labelText: 'password',
                                errorText: snapshot.error
                            ),
                          );
                        }
                     );
                  }
                

                例如:

                1. 将一些代码更改为已打开的(例如:流输入验证器)
                2. 保存应用程序(假设模拟器已经打开)
                3. 错误重现

                【讨论】:

                  【解决方案10】:

                  对于在 iOS 模拟器中遇到此错误的任何人,卸载并重新安装该应用程序对我有用。当我们过多地使用热重载时会发生这种情况。

                  我的 Flutter 版本:Flutter (Channel master, 1.22.0-2.0.pre.66, on Mac OS X 10.15.3 19D76, locale en-LK),我正在使用 android studio 构建

                  【讨论】:

                    【解决方案11】:

                    试试:

                    1. 停止程序
                    2. adb 卸载“$yourPackageName”
                    3. 扑干净
                    4. 再次运行程序

                    你可以在 "android/app/build.gradle" => defaultConfig/applicationId 中找到你的包名

                    Obs:还要记住,这只有在导致错误的问题已经解决时才有效。

                    这对我有用。

                    【讨论】:

                      【解决方案12】:

                      尝试以下方法:

                      1. 停止模拟。
                      2. 转到 Android 虚拟设备管理器。
                      3. 转到虚拟设备中的“操作”。
                      4. 点击向下箭头查看选项。
                      5. 点击“擦除数据”
                      6. 再次运行模拟。

                      它适用于 Android 设备。

                      【讨论】:

                        【解决方案13】:

                        我最近遇到了这个问题,我注意到使用热重载次数只会推送我的设计或任何存储的 sqlite 数据中的修改。

                        1. 所以在我的情况下,从应用程序中删除存储的数据。 (清除所有缓存)和
                        2. 运行 flutter clean 工作

                        【讨论】:

                          【解决方案14】:

                          最近我遇到了同样的错误。

                          在我的例子中,错误是由两个扩展小部件相互嵌套造成的。

                          通过删除父级扩展小部件,错误消失了。

                          【讨论】:

                          • 谢谢,这也解决了我的问题
                          • 人们应该更加重视这个答案,这确实是消息试图警告我们的问题,关于清理缓存的任何事情都只是出于巧合,这条消息准确地警告你您的小部件有问题。
                          • 它只是工作,@Renan Borges 上面的评论,你再正确不过了。
                          • 同样的问题,删除了我有的两个扩展的解决了这个问题。
                          【解决方案15】:

                          我在执行热重载时遇到了同样的问题,然后我执行了热重启并且它消失了。看起来像一个 Flutter 错误。

                          【讨论】:

                            猜你喜欢
                            • 2022-07-21
                            • 2021-11-13
                            • 2021-01-14
                            • 2019-09-08
                            • 2013-08-21
                            • 2013-06-25
                            • 1970-01-01
                            • 2019-05-25
                            • 2023-04-04
                            相关资源
                            最近更新 更多