12

I have a flutter app that makes many different http requests in different screens of the app. Now, I want to implement some general error handling, for example, whenever there is no connectivity, I want to show a SnackBar, no matter where I currently am in the app. I managed to write a method that gets called everytime there is an exception in one of my requests. Now, I want to show the SnackBar from within this method. But I don't have access to the BuildContext in this method, and I can't pass it as a parameter to the method either.

So, is there a way to show a SnackBar without having the context? For example, a method to get the context of the currently active screen, and then using it to show the SnackBar?

Apri
  • 1,241
  • 1
  • 8
  • 33

2 Answers2

14

Suggesting to use a package as pointed by Kaival is not the right way to go, since you won't learn the right solution for your problem other than relying on 3rd party packages and also over-engineering your app with those when sometimes not needed.

Tu use a SnackBar without a context it's actually very simple through a key. You can create a GlobalKey<ScaffoldState> wherever you want and assign it to the Scaffold where you want to display the SnackBar.

GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

Widget build(BuildContext context) {
   return Scaffold(key: _scaffoldKey);
}

and then anywhere you want, you can check its state to launch a SnackBar as such:

void foo() {
 if(_scaffoldKey.currentState != null) {
   _scaffoldKey.currentState.showSnackBar();
 }
}

You just need to make sure the state is mounted (this is, the Scaffold you want is available, before displaying it.

Just make sure that you are using the new ScaffoldMessenger API you may want to consider adding it to your root MaterialApp a ScaffoldMessengerState so you can use it everywhere.

final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
MaterialApp(
  scaffoldMessengerKey: rootScaffoldMessengerKey,
  home: ...
)

and call it accordingly

rootScaffoldMessengerKey.currentState.showSnackBar();

Refer to the docs for more info.

Miguel Ruivo
  • 16,035
  • 7
  • 57
  • 87
  • 1
    Thanks! This is actually really the better answer :) – Apri Aug 19 '21 at 12:08
  • This is a great simple answer making use of the latest Flutter capabilities. No external libraries are required. – Matthew Rideout Aug 28 '21 at 22:04
  • 1
    Sorry if this is obvious, but when you add the `scaffolMessengerKey` how do you access it outside of the MaterialApp? I cannot figure out how to call the `rootScaffoldMessengerKey`. – Dennis Ashford Sep 02 '22 at 12:21
  • @DennisAshford Probably initialize it as a global variable somewhere in one of your dart files. – Anakhand Nov 10 '22 at 08:10
2

Hi you could use a globalkey as a navigation key associated with your MaterialApp. That would allow you to also navigate eventually to an error scree or anywhere else.

With the globalkey, you will be able to retrieve the context everywhere (at least when your app is in foreground and there actually is a context).

Although it is not always really reccomended to have a global variable, you can do Something like this: In your main create a GlobalVariable class containing the key:

class GlobalVariable {
  /// This global key is used in material app for navigation through firebase notifications.
  static final GlobalKey<NavigatorState> navigatorState = GlobalKey<NavigatorState>();
}

Than declare the key as navigation key in your MaterialApp:

MaterialApp(
        navigatorKey: GlobalVariable.navigatorState,

Finally access the key and context everywhere:

GlobalVariable.navigatorState.currentContext
gbaccetta
  • 4,449
  • 2
  • 20
  • 30