In my app the user is presented with a puzzle, drawn by a re-implementation of Flutter's CustomerPainter class and accepting moves made by tapping on the Canvas. The Canvas is continually updated and re-drawn to show the moves. When the user makes the last move and completes a correct solution, the app should tell the user so. The app is using Flutter's AlertDialog to issue such messages to the user.
The problem is that the app is deep in the paint() method of CustomPainter when a solution situation is detected. Any attempt to issue a message at that point crashes the app. The message to the user does appear, but by that time the app has crashed. The error messages are either:
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception:
setState() or markNeedsBuild() called during build.
or
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception:
Build scheduled during frame.
These messages are followed by comprehensive advice as to what has happened and what to do. There are also several suggestions on Stack Overflow, but I cannot get any of them to work.
If I write SchedulerBinding.instance.addPostFrameCallback in my widget-build it fails to compile because it wants several parts from BindingBase. SchedulerBinding is a mixin. If I try to mixin BindingBase to my Widget, compilation fails again because BindingBase is a class, with a constructor, not a mixin.
If I go the async way, using Future executeAfterBuild(), the app compiles but crashes again, apparently because the async function executes straight away (as is normal) and is not scheduled after the widget-build, as suggested in some of the Stack Overflow posts. The app is definitely not in setState() when it crashes, so maybe marksNeedsBuild() is triggering the crash somehow.
I am using Flutter 2.8.2 and Dart 2.15.1, plus sound null safety. Has Flutter's widget-scheduling policy changed? The Stack Overflow posts I refer to are up to 3 years old.