I have a FlameGame using riverpod that is moved around the widget tree quite a bit, and reparented. Typically it's fine, but about 5% of the time an error is thrown: setState() or markNeedsBuild() called during build.
Full error log below, but the important part is #3, the forceBuild
method, which can be called during an existing widget build, but has no protections from calling setState
during a build.
setState() or markNeedsBuild() called during build.
This RiverpodAwareGameWidget<FooGame> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
RiverpodAwareGameWidget<FooGame>-[LabeledGlobalKey<RiverpodAwareGameWidgetState<FooGame>>#d5fcf]
The widget which was currently being built when the offending call was made was:
LayoutBuilder
#0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:5177:9)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5189:6)
#2 State.setState (package:flutter/src/widgets/framework.dart:1223:15)
#3 RiverpodAwareGameWidgetState.forceBuild (package:flame_riverpod/src/widget.dart:64:5)
#4 RiverpodComponentMixin.rebuildGameWidget (package:flame_riverpod/src/consumer.dart:124:42)
#5 RiverpodComponentMixin.onRemove (package:flame_riverpod/src/consumer.dart:112:7)
#6 Component._remove.<anonymous closure> (package:flame/src/components/core/component.dart:984:13)
#7 Iterable.every (dart:core/iterable.dart:427:16)
#8 Component.propagateToChildren (package:flame/src/components/core/component.dart:387:10)
#9 Component._remove (package:flame/src/components/core/component.dart:981:5)
#10 Component.handleLifecycleEventRemove (package:flame/src/components/core/component.dart:840:7)
#11 ComponentTreeRoot.processLifecycleEvents (package:flame/src/components/core/component_tree_root.dart:125:19)
#12 FlameGame.updateTree (package:flame/src/game/flame_game.dart:158:5)
#13 FlameGame.update (package:flame/src/game/flame_game.dart:152:7)
#14 GameWidgetState.build.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:flame/src/game/game_widget/game_widget.dart:387:37)
#15 GameWidgetState._protectedBuild (package:flame/src/game/game_widget/game_widget.dart:228:21)
#16 GameWidgetState.build.<anonymous closure>.<anonymous closure> (package:flame/src/game/game_widget/game_widget.dart:376:28)
#17 _LayoutBuilderElement._rebuildWithConstraints.updateChildCallback (package:flutter/src/widgets/layout_builder.dart:191:77)
#18 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:3038:19)
#19 _LayoutBuilderElement._rebuildWithConstraints (package:flutter/src/widgets/layout_builder.dart:231:12)
#20 RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:2719:59)
#21 PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1098:15)
#22 RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2719:14)
#23 RenderConstrainedLayoutBuilder.rebuildIfNecessary (package:flutter/src/widgets/layout_builder.dart:278:5)
#24 _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:369:5)
#25 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#26 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#27 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#28 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#29 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#30 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#31 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#32 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#33 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#34 RenderAspectRatio.performLayout (package:flutter/src/rendering/proxy_box.dart:580:12)
#35 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#36 RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:234:12)
#37 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#38 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#39 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#40 RenderPositionedBox.performLayout (package:flutter/src/rendering/shifted_box.dart:451:14)
#41 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#42 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:111:21)
#43 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#44 RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:291:14)
#45 RenderObject.layout (package:flutter/src/rendering/object.dart:2608:7)
#46 MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:173:12)
#47 _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:1092:7)
#48 MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:237:7)
#49 RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:404:14)
#50 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2446:7)
#51 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1052:18)
#52 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1065:15)
#53 RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:602:23)
#54 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:1164:13)
#55 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:468:5)
#56 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1397:15)
#57 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1318:9)
#58 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1176:5)
#59 _invoke (dart:ui/hooks.dart:312:13)
#60 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:419:5)
#61 _drawFrame (dart:ui/hooks.dart:283:31)
setState
should not be called during build, so the build phase will have to be checked so that setState is either called, or queued.
Hmm. I was doing it with navigation, but you could try placing a Game
in a layoutBuilder that changes the widget tree if the window size is even or odd. That'll trigger dozens of calls to rebuild as you resize a window.
No response
No response
No response
No response
All
No response
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too