mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Improve SnackBar error message when shown during build (#106658)
This commit is contained in:
parent
90d6303ff5
commit
0eed9adde7
@ -242,7 +242,7 @@ class ScaffoldMessengerState extends State<ScaffoldMessenger> with TickerProvide
|
||||
|
||||
// SNACKBAR API
|
||||
|
||||
/// Shows a [SnackBar] across all registered [Scaffold]s.
|
||||
/// Shows a [SnackBar] across all registered [Scaffold]s.
|
||||
///
|
||||
/// A scaffold can show at most one snack bar at a time. If this function is
|
||||
/// called while another snack bar is already visible, the given snack bar
|
||||
@ -289,10 +289,43 @@ class ScaffoldMessengerState extends State<ScaffoldMessenger> with TickerProvide
|
||||
},
|
||||
null, // SnackBar doesn't use a builder function so setState() wouldn't rebuild it
|
||||
);
|
||||
setState(() {
|
||||
_snackBars.addLast(controller);
|
||||
});
|
||||
_updateScaffolds();
|
||||
try {
|
||||
setState(() {
|
||||
_snackBars.addLast(controller);
|
||||
});
|
||||
_updateScaffolds();
|
||||
} catch (exception) {
|
||||
assert (() {
|
||||
if (exception is FlutterError) {
|
||||
final String summary = exception.diagnostics.first.toDescription();
|
||||
if (summary == 'setState() or markNeedsBuild() called during build.') {
|
||||
final List<DiagnosticsNode> information = <DiagnosticsNode>[
|
||||
ErrorSummary('The showSnackBar() method cannot be called during build.'),
|
||||
ErrorDescription(
|
||||
'The showSnackBar() method was called during build, which is '
|
||||
'prohibited as showing snack bars requires updating state. Updating '
|
||||
'state is not possible during build.',
|
||||
),
|
||||
ErrorHint(
|
||||
'Instead of calling showSnackBar() during build, call it directly '
|
||||
'in your on tap (and related) callbacks. If you need to immediately '
|
||||
'show a snack bar, make the call in initState() or '
|
||||
'didChangeDependencies() instead. Otherwise, you can also schedule a '
|
||||
'post-frame callback using SchedulerBinding.addPostFrameCallback to '
|
||||
'show the snack bar after the current frame.',
|
||||
),
|
||||
context.describeOwnershipChain(
|
||||
'The ownership chain for the particular ScaffoldMessenger is',
|
||||
),
|
||||
];
|
||||
throw FlutterError.fromParts(information);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
rethrow;
|
||||
}
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
|
||||
@ -2582,6 +2582,23 @@ void main() {
|
||||
expect(isDrawerOpen, false);
|
||||
expect(isEndDrawerOpen, false);
|
||||
});
|
||||
|
||||
testWidgets('ScaffoldMessenger showSnackBar throws an intuitive error message if called during build', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Builder(
|
||||
builder: (BuildContext context) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('SnackBar')));
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
final FlutterError error = tester.takeException() as FlutterError;
|
||||
final ErrorSummary summary = error.diagnostics.first as ErrorSummary;
|
||||
expect(summary.toString(), 'The showSnackBar() method cannot be called during build.');
|
||||
});
|
||||
}
|
||||
|
||||
class _GeometryListener extends StatefulWidget {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user