Flutter:提供程序类中出现“构建期间调用 setState() 或 markNeedsBuild()”错误

Jan*_*ker 4 provider flutter flutter-web

我收到一个错误

\n

setState() or markNeedsBuild() called during build.

\n

我使用提供程序进行状态管理,在 Flutter (Web) 中开发了一个带有侧边栏的 Web 仪表板。

\n

这是完整的堆栈跟踪:

\n
Restarted application in 243ms.\nGleap already initialized.\n[GoRouter] Full paths for routes:\n             => /login\n[GoRouter] setting initial location /events\n[GoRouter] Using MaterialApp configuration\nUser is signed in!\n\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa1 EXCEPTION CAUGHT BY FOUNDATION LIBRARY \xe2\x95\x9e\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\nThe following assertion was thrown while dispatching notifications for SidebarViewModel:\nsetState() or markNeedsBuild() called during build.\nThis _InheritedProviderScope<SidebarViewModel?> widget cannot be marked as needing to build because\nthe framework is already in the process of building widgets. A widget can be marked as needing to be\nbuilt during the build phase only if one of its ancestors is currently building. This exception is\nallowed because the framework builds parent widgets before children, which means a dirty descendant\nwill always be built. Otherwise, the framework might not visit this widget during this build phase.\nThe widget on which setState() or markNeedsBuild() was called was:\n  _InheritedProviderScope<SidebarViewModel?>\nThe widget which was currently being built when the offending call was made was:\n  LayoutBuilder\nWhen the exception was thrown, this was the stack:\ndart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49     throw_\npackages/flutter/src/widgets/framework.dart 4549:11                              <fn>\npackages/flutter/src/widgets/framework.dart 4563:14                              markNeedsBuild\npackages/provider/src/inherited_provider.dart 577:5                              markNeedsNotifyDependents\npackages/flutter/src/foundation/change_notifier.dart 351:24                      notifyListeners\npackages/vamos_events_dashboard/ui/widgets/sidebar/sidebar_view_model.dart 27:5  expandSidebar\npackages/vamos_events_dashboard/ui/pages/root_page.dart 18:57                    <fn>\npackages/flutter/src/widgets/layout_builder.dart 119:70                          layoutCallback\npackages/flutter/src/widgets/framework.dart 2605:19                              buildScope\npackages/flutter/src/widgets/layout_builder.dart 153:5                           [_layout]\npackages/flutter/src/rendering/object.dart 2246:59                               <fn>\npackages/flutter/src/rendering/object.dart 1035:15                               [_enableMutationsToDirtySubtrees]\npackages/flutter/src/rendering/object.dart 2246:7                                invokeLayoutCallback\npackages/flutter/src/widgets/layout_builder.dart 228:7                           rebuildIfNecessary\npackages/flutter/src/widgets/layout_builder.dart 316:5                           performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/custom_layout.dart 171:10                         layoutChild\npackages/flutter/src/material/scaffold.dart 1055:7                               performLayout\npackages/flutter/src/rendering/custom_layout.dart 240:7                          [_callPerformLayout]\npackages/flutter/src/rendering/custom_layout.dart 410:14                         performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/proxy_box.dart 1462:11                            performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/layout_helper.dart 56:10                          layoutChild\npackages/flutter/src/rendering/stack.dart 595:43                                 [_computeSize]\npackages/flutter/src/rendering/stack.dart 622:12                                 performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/proxy_box.dart 3737:13                            performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/widgets/overlay.dart 804:14                                 performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/custom_paint.dart 552:11                          performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/proxy_box.dart 120:7                              performLayout\npackages/flutter/src/rendering/object.dart 2135:7                                layout\npackages/flutter/src/rendering/box.dart 2418:11                                  layout\npackages/flutter/src/rendering/view.dart 170:7                                   performLayout\npackages/flutter/src/rendering/object.dart 1973:7                                [_layoutWithoutResize]\npackages/flutter/src/rendering/object.dart 999:17                                flushLayout\npackages/flutter/src/rendering/binding.dart 513:19                               drawFrame\npackages/flutter/src/widgets/binding.dart 884:13                                 drawFrame\npackages/flutter/src/rendering/binding.dart 378:5                                [_handlePersistentFrameCallback]\npackages/flutter/src/scheduler/binding.dart 1175:15                              [_invokeFrameCallback]\npackages/flutter/src/scheduler/binding.dart 1104:9                               handleDrawFrame\npackages/flutter/src/scheduler/binding.dart 881:7                                <fn>\ndart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:19          internalCallback\nThe SidebarViewModel sending notification was:\n  Instance of 'SidebarViewModel'\n\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\n
Run Code Online (Sandbox Code Playgroud)\n

这是三个相关的类:

\n

根页面:

\n
class RootPage extends StatelessWidget {\n  const RootPage({required this.widget});\n\n  final Widget widget;\n\n  @override\n  Widget build(BuildContext context) {\n    final SidebarViewModel sidebarViewModel = context.read<SidebarViewModel>();\n\n    return Scaffold(\n      body: LayoutBuilder(\n        builder: (_, BoxConstraints constraints) {\n          constraints.maxWidth > 1100 ? sidebarViewModel.expandSidebar() : sidebarViewModel.collapseSidebar();\n          return Row(children: [const Sidebar(), Expanded(child: widget)]);\n        },\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

侧边栏:

\n
class Sidebar extends StatelessWidget {\n  const Sidebar({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    final SidebarViewModel sidebarViewModel = context.watch<SidebarViewModel>();\n    // final SidebarViewModel sidebarViewModel = Provider.of<SidebarViewModel>(context, listen: false);\n\n    return SizedBox(\n      width: sidebarViewModel.isExpanded ? 250 : 90,\n      child: Padding(\n        padding: const EdgeInsets.all(20.0),\n        child: Column(\n          children: [\n            SidebarEntry(\n              title: 'Profil',\n              icon: Icons.account_circle_outlined,\n              onTap: () {\n                if (sidebarViewModel.selectedItem != SidebarItem.profile) {\n                  sidebarViewModel.selectItem(SidebarItem.profile);\n                  context.go(ProfilePage.route);\n                }\n              },\n              isSelected: sidebarViewModel.selectedItem == SidebarItem.profile,\n            ),\n            SidebarEntry(\n              title: 'Organisation',\n              icon: Icons.business_center_outlined,\n              onTap: () {\n                if (sidebarViewModel.selectedItem != SidebarItem.organization) {\n                  sidebarViewModel.selectItem(SidebarItem.organization);\n                  context.go(OrganizationPage.route);\n                }\n              },\n              isSelected: sidebarViewModel.selectedItem == SidebarItem.organization,\n            ),\n            SidebarEntry(\n              title: 'Veranstaltungen',\n              icon: Icons.calendar_month_rounded,\n              onTap: () {\n                if (sidebarViewModel.selectedItem != SidebarItem.events) {\n                  sidebarViewModel.selectItem(SidebarItem.events);\n                  context.go(EventsPage.route);\n                }\n              },\n              isSelected: sidebarViewModel.selectedItem == SidebarItem.events,\n            ),\n            const Spacer(),\n            SidebarEntry(\n              title: 'Abmelden',\n              icon: Icons.logout,\n              onTap: () => context.read<AuthService>().signOut(),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

侧边栏视图模型:

\n
enum SidebarItem { profile, organization, events }\n\nclass SidebarViewModel with ChangeNotifier {\n  SidebarViewModel();\n\n  SidebarItem _selectedItem = SidebarItem.events;\n  bool _isExpanded = false;\n\n  SidebarItem get selectedItem => _selectedItem;\n  bool get isExpanded => _isExpanded;\n\n  void selectItem(SidebarItem item) {\n    _selectedItem = item;\n    notifyListeners();\n  }\n\n  void toggleSidebarExpansion() {\n    _isExpanded = !_isExpanded;\n    notifyListeners();\n  }\n\n  void expandSidebar() {\n    if (_isExpanded) return;\n    _isExpanded = true;\n    notifyListeners();\n  }\n\n  void collapseSidebar() {\n    if (!_isExpanded) return;\n    _isExpanded = false;\n    notifyListeners();\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果有人能帮助我解决这个错误,我会很高兴。仅当在 ViewModel 中调用“expandSidebar”或“collapseSidebar”方法时才会出现该错误。换句话说:当我使 Web 窗口变小或变大时,它会触发 RootPage 中的构建方法,然后触发展开或折叠侧边栏方法。

\n

jos*_*xha 7

该错误意味着您的build()方法中的某处要么被调用setState(),要么markNeedsBuild()被调用。所以 build() 函数基本上会在尚未完成时一次又一次地调用自身。

一个简单的解决方法可能是使用后帧回调

// build method of your RootPage widget
@override
  Widget build(BuildContext context) {
    final SidebarViewModel sidebarViewModel = context.read<SidebarViewModel>();

    return Scaffold(
      body: LayoutBuilder(
        builder: (_, BoxConstraints constraints) {
          WidgetsBinding.instance!.addPostFrameCallback((_) {
              // executes after build
              constraints.maxWidth > 1100 
                  ? sidebarViewModel.expandSidebar() 
                  : sidebarViewModel.collapseSidebar();
          });
          return Row(children: [const Sidebar(), Expanded(child: widget)]);
        },
      ),
    );
  }
Run Code Online (Sandbox Code Playgroud)