FlutterError : The key [LabeledGlobalKey<FormState>] was used by multiple widgets

FlutterError : The key [LabeledGlobalKey<FormState>] was used by multiple widgets

我在尝试导航到 menu_screen 小部件时遇到错误。我很确定 GlobalKey menuFormKey 没有在另一个小部件中使用,但我不明白为什么我会遇到这个问题。

有menu_screen的代码:

import 'dart:async';

import 'package:flutter/material.dart';

class MenuScreen extends StatefulWidget {
  bool dark;
  Menu menu;
  MenuScreen({Key? key, required this.dark, required this.menu})
      : super(key: RIKeys.riKey3);

  @override
  State<MenuScreen> createState() => _MenuScreenState();
  static String id = "MenuScreen";
}

class _MenuScreenState extends State<MenuScreen> {
  final StreamController<Menu> _currentMenuStreamCtrl =
      StreamController<Menu>.broadcast();
  Stream<Menu> get onCurrentMenuChanged => _currentMenuStreamCtrl.stream;
  void updateCurrentMenuUI() => _currentMenuStreamCtrl.add(widget.menu);
  GlobalKey<FormState> menuformKey =
      GlobalKey<FormState>(debugLabel: "menu form Key");
  @override
  Widget build(BuildContext context) {
    Size deviceSize = MediaQuery.of(context).size;
    Orientation deviceOrientation = MediaQuery.of(context).orientation;
    bool isPortrait = deviceOrientation == Orientation.portrait;
    double screenWidth = isPortrait ? deviceSize.width : deviceSize.height;
    double screenHeight = isPortrait ? deviceSize.height : deviceSize.width;
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          appBar: AppBar(
            leading: IconButton(
              icon: Icon(Icons.arrow_back),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
            title: Text(
              "Modify Menu",
              style: TextStyle(
                color: widget.dark ? Colors.black : Colors.white,
              ),
            ),
            actions: [
              IconButton(
                onPressed: () {
                  if (menuformKey.currentState!.validate()) {
                    menuformKey.currentState!.save();
                    Navigator.pop(context);
                  }
                },
                icon: Icon(
                  Icons.done_outline,
                  color: widget.dark ? Colors.black : Colors.white,
                ),
              ),
            ],
            backgroundColor:
                !widget.dark ? backgroundDarkColor : backgroundLightColor,
          ),
          body: StreamBuilder(
            initialData: widget.menu,
            stream: onCurrentMenuChanged,
            builder: (context, AsyncSnapshot<Menu> snapshot) {
              late Widget builtWidget;
              if (snapshot.hasData) {
                builtWidget = ListView.builder(
                  itemCount: widget.menu.categories.length,
                  itemBuilder: (context, i) {
                    Category categoryItem = widget.menu.categories[i];
                    return Form(
                      key: menuformKey,
                      child: ListView(
                        shrinkWrap: true,
                        children: [
                          Padding(
                            padding: EdgeInsets.symmetric(
                                horizontal: screenWidth * .1),
                            child: TextFormField(
                              initialValue: categoryItem.title,
                              onSaved: (value) {
                                categoryItem.setTitle = value!;
                              },
                            ),
                          ),
                          Expanded(
                            child: ListView.builder(
                              shrinkWrap: true,
                              itemCount: categoryItem.items.length,
                              itemBuilder: (context, j) {
                                Meal mealItem = categoryItem.items[j];
                                return Container(
                                  width: double.infinity,
                                  height: screenHeight * .1,
                                  color: widget.dark
                                      ? primaryDarkColor
                                      : primaryLightColor,
                                  child: ListTile(
                                    leading: Stack(
                                      alignment: Alignment.topLeft,
                                      children: [
                                        Container(
                                          width: screenWidth * .1,
                                          height: screenWidth * .2,
                                          decoration: BoxDecoration(
                                            image: DecorationImage(
                                                image: AssetImage(
                                                    mealItem.imgPath),
                                                fit: BoxFit.fill),
                                          ),
                                        ),
                                        IconButton(
                                          onPressed: () {
                                            /*Change Image Function*/
                                          },
                                          icon: Icon(
                                            Icons.edit,
                                            color: Colors.white,
                                          ),
                                        ),
                                      ],
                                    ),
                                    title: TextFormField(
                                      initialValue: mealItem.name,
                                      onSaved: (value) {
                                        mealItem.setName = value!;
                                      },
                                    ),
                                    subtitle: TextFormField(
                                      initialValue: "${mealItem.price}",
                                      onSaved: (value) {
                                        mealItem.setPrice =
                                            double.parse(value!);
                                      },
                                    ),
                                    trailing: IconButton(
                                      onPressed: () {
                                        categoryItem.items.remove(mealItem);
                                      },
                                      icon: Icon(
                                        Icons.delete,
                                        color: Colors.red,
                                      ),
                                    ),
                                  ),
                                );
                              },
                            ),
                          ),
                        ],
                      ),
                    );
                  },
                );
              } else if (snapshot.error != null) {
                builtWidget = Text("error : ${snapshot.error}");
              } else if (!snapshot.hasData) {
                builtWidget = Text("No data");
              } else if (snapshot.connectionState == ConnectionState.waiting) {
                builtWidget = Text("Waiting for Connection");
              }
              return builtWidget;
            },
          ),
        ),
      ),
    );
  }
}

这是完整的错误描述:

FlutterError (Multiple widgets used the same GlobalKey. The key [LabeledGlobalKey#f9b7f menu form Key] was used by multiple widgets. The parents of those widgets were:

  • RepaintBoundary(renderObject: RenderRepaintBoundary#522fa relayoutBoundary=up4 NEEDS-LAYOUT NEEDS-PAINT)
  • RepaintBoundary(renderObject: RenderRepaintBoundary#ef78c relayoutBoundary=up4) A GlobalKey can only be specified on one widget at a time in the widget tree.)

我的错误是在 ListView.builder() 中包含了表格。

所以,我通过将代码更改为这样解决了错误:

Form(
  key: menuformKey,
  child: ListView.builder(
     shrinkWrap: true,
     itemCount: widget.menu.categories.length,
     itemBuilder: (context, i) {
     Category categoryItem = widget.menu.categories[i];
     return ListView(
         primary: false,
         shrinkWrap: true,
         children: [
             Column(
                children: [
                   Padding(
                      padding: EdgeInsets.symmetric(
                      horizontal: screenWidth * .1),
                      child: TextFormField(
                      initialValue: categoryItem.title,
                      onSaved: (value) {
                      categoryItem.setTitle = value!;
                      },
                      ),
                   ),
                   ListView.builder(
                      primary: true,
                      shrinkWrap: true,
                      itemCount: categoryItem.items.length,
                      itemBuilder: (context, j) {
                      Meal mealItem = categoryItem.items[j];
                          return Container(
                             margin: EdgeInsets.only(
                                top: 20, left: 20, right: 20),
                             width: double.infinity,
                             height: screenHeight * .15,
                             color: widget.dark
                             ? primaryDarkColor
                             : primaryLightColor,
                               child: ListTile(
                                  leading: Container(
                                    height: screenHeight * .5,
                                    width: screenWidth * .2,
                                    child: Stack(
                                      children: [
                                        FittedBox(
                                          child:  Image.asset(mealItem.imgPath,)
                                        ),
                                        IconButton(
                                          onPressed: () async {
                                            final XFile? pickedImage =
                                                await _picker.pickImage(
                                                    source:
                                                        ImageSource.gallery);
                                            if (pickedImage != null) {
                                              setState(
                                                () {
                                                  mealItem.setImgPath =
                                                      pickedImage.path;
                                                  _images[j] =
                                                      File(pickedImage.path);
                                                  print(pickedImage.path);
                                                },
                                              );
                                            }
                                          },
                                          icon: Icon(
                                            Icons.edit,
                                            color: Colors.white,
                                            size: 20,
                                          ),
                                        ),
                                      ],
                                    ),
                                  ),
                                  title: TextFormField(
                                    initialValue: mealItem.name,
                                    onSaved: (value) {
                                      mealItem.setName = value!;
                                    },
                                  ),
                                  subtitle: TextFormField(
                                    initialValue: "${mealItem.price}",
                                    onSaved: (value) {
                                      mealItem.setPrice = double.parse(value!);
                                    },
                                  ),
                                  trailing: IconButton(
                                    onPressed: () {
                                      categoryItem.items.remove(mealItem);
                                    },
                                    icon: Icon(
                                      Icons.delete,
                                      color: Colors.red,
                                    ),
                                  ),
                                ),
                              );
                            },
                          ),
                        ],
                      );
                    },
                  ),
                );