after_first_frame_mixin 1.0.0
after_first_frame_mixin: ^1.0.0 copied to clipboard
Run code after the first layout of a widget has been performed, i.e. after the first frame has been displayed - as a mixin or as a widget.
after_first_frame_mixin #
Run code after the first layout of a widget has been performed, i.e. after the first frame has been displayed.
initState runs before layout, so the context it sees has no size, no route
transition in place and no Scaffold to show a snack bar in. This package gives
you a callback that runs once the frame is on screen, as a mixin or as a
widget.
Installation #
dependencies:
after_first_frame_mixin: ^1.0.0
Requires Dart 3.8 / Flutter 3.32 or newer.
Usage #
As a mixin #
class HomeScreenState extends State<HomeScreen>
with AfterFirstFrameMixin<HomeScreen> {
@override
Widget build(BuildContext context) => const Center(child: Text('Example'));
@override
FutureOr<void> afterFirstFrame(BuildContext context) {
showDialog<void>(
context: context,
builder: (BuildContext context) =>
const AlertDialog(content: Text('Hello World')),
);
}
}
As a widget #
For a subtree that would otherwise have no reason to be stateful:
AfterFirstFrame(
onFirstFrame: (BuildContext context) => ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('Ready'))),
child: const HomeBody(),
)
Later frames #
afterNextFrame is the counterpart for everything after the first frame — for
instance to measure a layout that a setState has just changed. It can be
called at any point in the widget's life and schedules a frame if none is
pending.
void _grow() {
setState(() => _width += 40);
afterNextFrame((_) {
final RenderBox box = _key.currentContext!.findRenderObject()! as RenderBox;
setState(() => _measured = box.size);
});
}
hasRenderedFirstFrame tells you which side of the first frame you are on:
if (hasRenderedFirstFrame) {
// safe to touch layout-dependent things
}
API #
| Member | Description |
|---|---|
AfterFirstFrameMixin<T> |
Mixin on State<T>. Implement afterFirstFrame. |
afterFirstFrame(BuildContext) |
Called once, after the first frame. May return a Future. |
afterNextFrame(callback) |
Runs callback after the next frame. Callable at any time. |
hasRenderedFirstFrame |
Whether the first frame has been displayed. |
AfterFirstFrame |
Widget form: onFirstFrame + child. |
AfterFrameCallback |
FutureOr<void> Function(BuildContext context). |
Notes #
- Callbacks never run after the
Statehas been unmounted. - Errors — including those thrown by an asynchronous callback — are reported
through
FlutterError.reportError, so they reachFlutterError.onErrorandtester.takeException()instead of escaping as unhandled async errors. - Scheduling relies on
WidgetsBinding.instance.endOfFrame. If the device screen is off, frames are not produced and the callback waits.
Example #
A runnable app demonstrating all three APIs is in the /example folder.