Flutter - Looking up a deactivated widget's ancestor is unsafe with Provider package, FireStore authentication
Problem:
You are getting the error because of this code:
Scaffold.of(ctx).showSnackBar(SnackBar( content: Text(message), ));
The Scaffold.of(context)
is attempting to look up the scaffold in a widget tree that is no longer above it.
Here is how the issue is arising:
- The login call is fired off asynchronously:
String message = await provider.signIn(...);
- While the call is being awaited, the parents of the button widget may have changed, or the button itself may have been removed from the tree.
- Then, when
Scaffold.of(ctx).showSnackbar(...)
is called, it is now attempting to look up a scaffold in a widget tree that doesn't exist.
Solution:
There are a few solutions. One of them is to use a global scaffold which wraps each of your routes. That scaffold key can then be used to show snackbars.
Here is how that could be done:
Add a scaffold to your MaterialApp builder. Make sure to use the global key.
final globalScaffoldKey = GlobalKey<ScaffoldState>();class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MultiProvider( ... child: MaterialApp( builder: (context, child) { return Scaffold( key: globalScaffoldKey, body: child, ); },...
You could then use that key to show snackbars through a global function:
void showSnackbar(String message) { var currentScaffold = globalScaffoldKey.currentState; currentScaffold.hideCurrentSnackBar(); // If there is a snackbar visible, hide it before the new one is shown. currentScaffold.showSnackBar(SnackBar(content: Text(message))); }
Usage would look like this, and you can safely call it from anywhere in your code:
showSnackbar('My Snackbar Message')