flutter 多个微件使用同一GlobalKey

5lhxktic  于 2022-12-19  发布在  Flutter
关注(0)|答案(1)|浏览(145)

我看到这个错误在过去的3-4天**“多个小部件使用相同的GlobalKey。"**。我一直在尝试建立一个网页与PageView。builder和当我的网页到达商店图片部分我的代码抛出这个异常。

======== Exception caught by widgets library =======================================================
The following assertion was thrown while finalizing the widget tree:
Multiple widgets used the same GlobalKey.

The key [LabeledGlobalKey<FormState>#5908a] was used by multiple widgets. The parents of those widgets were different widgets that both had the following description:
  Expanded(flex: 1)
A GlobalKey can only be specified on one widget at a time in the widget tree.
When the exception was thrown, this was the stack: 
#0      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:flutter/src/widgets/framework.dart:2883:13)
#1      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13)
#2      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>.<anonymous closure> (package:flutter/src/widgets/framework.dart:2827:20)
#3      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13)
#4      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure> (package:flutter/src/widgets/framework.dart:2822:36)
#5      BuildOwner._debugVerifyGlobalKeyReservation (package:flutter/src/widgets/framework.dart:2891:6)
#6      BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2950:11)
#7      BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:3032:8)
#8      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:885:19)
#9      RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5)
#10     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15)
#11     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9)
#12     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5)
#16     _invoke (dart:ui/hooks.dart:150:10)
#17     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#18     _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
====================================================================================================

======== Exception caught by widgets library =======================================================
The following assertion was thrown while finalizing the widget tree:
Multiple widgets used the same GlobalKey.

The key [LabeledGlobalKey<FormState>#5908a] was used by multiple widgets. The parents of those widgets were different widgets that both had the following description:
  Expanded(flex: 1)
A GlobalKey can only be specified on one widget at a time in the widget tree.
When the exception was thrown, this was the stack: 
#0      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:flutter/src/widgets/framework.dart:2883:13)
#1      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13)
#2      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>.<anonymous closure> (package:flutter/src/widgets/framework.dart:2827:20)
#3      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13)
#4      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure> (package:flutter/src/widgets/framework.dart:2822:36)
#5      BuildOwner._debugVerifyGlobalKeyReservation (package:flutter/src/widgets/framework.dart:2891:6)
#6      BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2950:11)
#7      BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:3032:8)
#8      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:885:19)
#9      RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5)
#10     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15)
#11     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9)
#12     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5)
#16     _invoke (dart:ui/hooks.dart:150:10)
#17     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#18     _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
====================================================================================================

======== Exception caught by widgets library =======================================================
The following assertion was thrown while finalizing the widget tree:
Multiple widgets used the same GlobalKey.

The key [LabeledGlobalKey<FormState>#5908a] was used by multiple widgets. The parents of those widgets were different widgets that both had the following description:
  Expanded(flex: 1)
A GlobalKey can only be specified on one widget at a time in the widget tree.
When the exception was thrown, this was the stack: 
#0      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:flutter/src/widgets/framework.dart:2883:13)
#1      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13)
#2      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>.<anonymous closure> (package:flutter/src/widgets/framework.dart:2827:20)
#3      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13)
#4      BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure> (package:flutter/src/widgets/framework.dart:2822:36)
#5      BuildOwner._debugVerifyGlobalKeyReservation (package:flutter/src/widgets/framework.dart:2891:6)
#6      BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2950:11)
#7      BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:3032:8)
#8      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:885:19)
#9      RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5)
#10     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15)
#11     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9)
#12     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5)
#16     _invoke (dart:ui/hooks.dart:150:10)
#17     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#18     _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
====================================================================================================

在得到这个异常后,当我点击屏幕时,我多次得到相同的异常(7次)
这是我的代码,我使用MVVM架构和riverpod。

import 'package:b2b/export.dart';

class CreateStorePage extends ConsumerStatefulWidget {
  const CreateStorePage({
    Key? key,
  }) : super(key: key);

  @override
  ConsumerState<ConsumerStatefulWidget> createState() =>
      _CreateStorePageState();
}

class _CreateStorePageState
    extends BaseConsumerState<CreateStorePage, CreateStoreViewModel> {
  GlobalKey<ScaffoldState> createStoreScaffoldKey = GlobalKey<ScaffoldState>();

  @override
  void initState() {
    super.initState();
    viewModel().pageController = PageController(initialPage: viewModel().index);
    viewModel().storeNameFormKey = GlobalKey<FormState>();
    viewModel().discountAmountFormKey = GlobalKey<FormState>();
    viewModel().eligibleFormKey = GlobalKey<FormState>();
    viewModel().getCategoriesData();
  }

  @override
  Widget customBuild(BuildContext context) {
    return WillPopScope(
      onWillPop: () async => false,
      child: GestureDetector(
        onTap: () {
          FocusScope.of(context).unfocus();
          viewModel().cancelBorderColor();
        },
        child: Scaffold(
          key: createStoreScaffoldKey,
          backgroundColor: colors.primaryLight,
          body: SafeArea(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                LinearProgressIndicator(
                  valueColor: AlwaysStoppedAnimation(colors.accentPrimary),
                  value: viewModel().progressIndicatorValue,
                  backgroundColor: colors.accentPrimaryopac,
                  minHeight: sizes.heightRatio! * 7,
                ),
                Expanded(
                  child: PageView.builder(
                    physics: const NeverScrollableScrollPhysics(),
                    controller: viewModel().pageController,
                    itemBuilder: (context, index) {
                      return SizedBox(
                        height: 500,
                        child: SingleChildScrollView(
                          physics: const BouncingScrollPhysics(),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              verticalSpacer(12),
                              Padding(
                                padding: EdgeInsets.symmetric(
                                  horizontal: horizontalValue(16),
                                  vertical: verticalValue(16),
                                ),
                                child:
                                    BoldTitleText(Constants.headingName[index]),
                              ),
                              verticalSpacer(49),
                              viewModel().getBlockList()[0]
                                  ? Padding(
                                      padding: EdgeInsets.symmetric(
                                        horizontal: horizontalValue(16),
                                      ),
                                      child: SizedBox(
                                        child: Column(
                                          crossAxisAlignment:
                                              CrossAxisAlignment.start,
                                          children: [
                                            AapayTextView(
                                              showCursor: true,
                                              readOnly: false,
                                              containerColor: colors.lightGrey,
                                              hasTextLengthLimitation: false,
                                              textFieldEnable: true,
                                              isPhoneField: false,
                                              textFieldHintText: Constants
                                                  .enterYourBusinessName,
                                              keyboardType: TextInputType.text,
                                              onTap: (value, formKey) {
                                                viewModel().setFormKey(1);
                                                viewModel().texFieldCheck(
                                                    value, formKey);
                                              },
                                              hasSuffix:
                                                  viewModel().nameFieldSuffix,
                                              formKey:
                                                  viewModel().storeNameFormKey,
                                              controller:
                                                  viewModel().nameController,
                                              boarderColor:
                                                  viewModel().boarderColor,
                                              containerBorderColor: () {
                                                viewModel().setBoarderColor();
                                              },
                                              cancelBorderColor: () {
                                                viewModel().cancelBorderColor();
                                              },
                                              onTextFieldTap: () {},
                                              showValidation: () {
                                                viewModel()
                                                    .showValidationError();
                                              },
                                              cancelValidation: () {
                                                viewModel()
                                                    .cancelValidationError();
                                              },
                                              allowOtherCharacters: false,
                                            ),
                                            Visibility(
                                              visible:
                                                  viewModel().showValidation,
                                              child: ValidationError(
                                                textMessage: viewModel()
                                                        .storeBusinessNameTextViewStateAuthorized
                                                    ? ''
                                                    : Constants
                                                        .enterYourValidBusinessName,
                                              ),
                                            ),
                                          ],
                                        ),
                                      ),
                                    )
                                  : const SizedBox.shrink(),
                              verticalSpacer(10),
                              //Shopping Discount Block
                              viewModel().getBlockList()[1]
                                  ? ScreenTab(
                                      selected:
                                          viewModel().getDiscountChipList(),
                                      isSelected: viewModel().discount1,
                                      containerBorderColor: () {},
                                      cancelBorderColor: () {},
                                      formKey:
                                          viewModel().discountAmountFormKey,
                                      text: Constants
                                          .howMuchDiscountWillYouGiveOnTheShopping,
                                      onChipTap: (int value, String text) {
                                        viewModel()
                                            .setDiscountTextfieldInitialVal(
                                                text);
                                        viewModel().isDiscountChipPressed();
                                      },
                                      textFieldInitialVal:
                                          viewModel().discountTextFieldVal,
                                      tabController:
                                          viewModel().discountAMountController,
                                      onTextFieldChange: (String value,
                                          GlobalKey<FormState> formKey) {
                                        viewModel().setFormKey(2);
                                        viewModel()
                                            .texFieldCheck(value, formKey);
                                      },
                                      isError: viewModel()
                                          .discountTextViewStateAuthorized,
                                      hasSuffix:
                                          viewModel().discountFieldSuffix,
                                      boarderColor: false,
                                    )
                                  : const SizedBox.shrink(),
                              verticalSpacer(20),
                              //Eligible Discount Block
                              viewModel().getBlockList()[2]
                                  ? ScreenTab(
                                      selected:
                                          viewModel().getEligibleForDiscount(),
                                      isSelected: viewModel().discount2,
                                      containerBorderColor: () {},
                                      cancelBorderColor: () {},
                                      boarderColor: false,
                                      formKey: viewModel().eligibleFormKey,
                                      text: Constants
                                          .afterHowMuchPurchaseCustomersWillBeEligible,
                                      onChipTap: (int value, String text) {
                                        viewModel()
                                            .setEligibleTextfieldInitialVal(
                                                text);
                                        viewModel().isEligibleChipPressed();
                                      },
                                      textFieldInitialVal:
                                          viewModel().eligibleTextFieldVal,
                                      tabController: viewModel()
                                          .eligibleCriteriaController,
                                      onTextFieldChange: (String value,
                                          GlobalKey<FormState> formKey) {
                                        viewModel().setFormKey(3);
                                        viewModel()
                                            .texFieldCheck(value, formKey);
                                      },
                                      isError: viewModel()
                                          .eligibilityTextViewStateAuthorized,
                                      hasSuffix:
                                          viewModel().eligibilityFieldSuffix,
                                    )
                                  : const SizedBox.shrink(),
                              verticalSpacer(20),
                              //Categories Block
                              viewModel().getBlockList()[3]
                                  ? CategoriesBlock(
                                      blockList: viewModel().getBlockList(),
                                      buttonState: (value) =>
                                          viewModel().buttonState(value),
                                      getList: viewModel().getList(),
                                    )
                                  : const SizedBox.shrink(),
                              verticalSpacer(30),
                              //Store Image Block
                              viewModel().getBlockList()[6]
                                  ? StoreImage(
                                      image: viewModel().image,
                                      getImage: (value) {
                                        viewModel().getImage(value);
                                      },
                                      blockList: viewModel().getBlockList(),
                                    )
                                  : const SizedBox.shrink(),
                              verticalSpacer(30),
                              //Branches Block
                              viewModel().getBlockList()[7]
                                  ? const StoreBranches()
                                  : const SizedBox.shrink(),
                              verticalSpacer(30),
                              //Branches List
                              viewModel().getBlockList()[7]
                                  ? BranchesList(
                                      itemCount:
                                          viewModel().getBranchList().length,
                                      getLocationNameList:
                                          viewModel().getLocationNameList(),
                                      getBranchesData:
                                          viewModel().getBranchList(),
                                    )
                                  // Container(
                                  //         padding: EdgeInsets.symmetric(
                                  //           horizontal: horizontalValue(20),
                                  //         ),
                                  //         height: (sizes.heightRatio! * 35) *
                                  //             viewModel().getBranchList().length,
                                  //         child: IntrinsicHeight(
                                  //           child: ListView.separated(
                                  //             shrinkWrap: true,
                                  //             itemCount: viewModel()
                                  //                 .getBranchList()
                                  //                 .length,
                                  //             itemBuilder:
                                  //                 (BuildContext context, index) {
                                  //               return TextWidget(
                                  //                 text:
                                  //                     '${viewModel().getLocationNameList()[index]} ( ${viewModel().getBranchList()[index].name})',
                                  //                 textSize: 17,
                                  //                 fontFamilyType:
                                  //                     FontFamily.manropeMedium,
                                  //                 textColor: colors.primaryDark,
                                  //               );
                                  //             },
                                  //             separatorBuilder: (_, index) {
                                  //               return verticalSpacer(10);
                                  //             },
                                  //           ),
                                  //         ),
                                  //       )
                                  : const SizedBox.shrink(),
                            ],
                          ),
                        ),
                      );
                    },
                    onPageChanged: (index) {
                      viewModel().index == 7 ? viewModel().index : index;
                      print(viewModel().index);
                      viewModel().setBlockState(
                        index,
                      );
                      viewModel().index = viewModel().index + 1;
                      viewModel().refreshState();
                    },
                    itemCount: viewModel().getBlockList().length,
                  ),
                )
              ],
            ),
          ),
          resizeToAvoidBottomInset: true,
          bottomNavigationBar: Padding(
            padding: EdgeInsets.symmetric(
              horizontal: horizontalValue(20),
              vertical: verticalValue(20),
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                FilledButton(
                  color: viewModel().filledButtonState
                      ? colors.accentPrimary
                      : CustomizedTheme.blackOpac01,
                  textColor: colors.primaryLight,
                  showLockIcon: false,
                  isLoading: false,
                  text: Constants.branchAddedVal
                      ? Constants.done
                      : Constants.next,
                  onTap: viewModel().filledButtonState
                      ? () {
                          if (viewModel().index == 8 &&
                              Constants.branchAddedVal == false) {
                            GoRouter.of(createStoreScaffoldKey
                                    .currentState!.context)
                                .push(mapAddLocationPageRoute);
                            FocusScope.of(createStoreScaffoldKey
                                    .currentState!.context)
                                .unfocus();
                          } else if (viewModel().index == 8 &&
                              Constants.branchAddedVal == true) {
                            viewModel().navigateToHomePage();
                            FocusScope.of(createStoreScaffoldKey
                                    .currentState!.context)
                                .unfocus();
                          } else {
                            viewModel().pageController.nextPage(
                                duration: const Duration(milliseconds: 1),
                                curve: Curves.linear);
                            FocusScope.of(createStoreScaffoldKey
                                    .currentState!.context)
                                .unfocus();
                          }
                        }
                      : null,
                ),
                viewModel().getBlockList()[7]
                    ? verticalSpacer(24)
                    : const SizedBox.shrink(),
                viewModel().getBlockList()[7] && !Constants.branchAddedVal
                    ? FilledButton(
                        text: Constants.finishAndAddLater,
                        onTap: viewModel().filledButtonState
                            ? () {
                                GoRouter.of(createStoreScaffoldKey
                                        .currentState!.context)
                                    .go(homePageRoute);
                                FocusScope.of(createStoreScaffoldKey
                                        .currentState!.context)
                                    .unfocus();
                              }
                            : null,
                        color: viewModel().filledButtonState
                            ? colors.accentPrimary
                            : CustomizedTheme.blackOpac01,
                        textColor: colors.primaryLight,
                        showLockIcon: false,
                        isLoading: false,
                      )
                    : const SizedBox.shrink(),
              ],
            ),
          ),
        ),
      ),
    );
  }

  @override
  StateNotifierProvider<BaseViewModel, BaseState> getProvider() =>
      createStoreViewModel;

  @override
  void initializeListener(
      StateNotifierProvider<BaseViewModel, BaseState> provider) {
    ref.listen(
      provider,
      (previous, next) {
        switch (next.runtimeType) {
          case RefreshCreateStorePage:
            {
              setState(() {});
              break;
            }
          case NavigateToHomePageState:
            {
              GoRouter.of(createStoreScaffoldKey.currentState!.context)
                  .go(homePageRoute);
              break;
            }
        }
      },
    );
  }
}
h9vpoimq

h9vpoimq1#

对于不同的小部件多次使用相同的GlobalKey,最好使用基于索引或uuid的单独键

...
viewModel().storeNameFormKey = GlobalKey<FormState>();
viewModel().discountAmountFormKey = GlobalKey<FormState>();
viewModel().eligibleFormKey = GlobalKey<FormState>();
...

相关问题