How to pass provider with Navigator? How to pass provider with Navigator? dart dart

How to pass provider with Navigator?


You can easily pass the provider in the Navigator by creating a new provider when Navigating to a new page.

 Navigator.of(context).push(      MaterialPageRoute(        builder: (BuildContext context) => Provider(          create: (context) => InventoryItem(),          builder: (context, child) => ProductDetails(),        ),      ),    );

Here either create a new object InventoryItem() or pass the existing provider object.


You would need to make the Provider appear above the Navigator Widget to be an anchestor of the current Widget. That means, it must reside above the MaterialApp(), CupertinoApp() or whatever Directionality() you might use.

Please refer to following links for more information about InheritedWidget.

https://medium.com/@mehmetf_71205/inheriting-widgets-b7ac56dbbeb1

https://www.youtube.com/watch?v=Zbm3hjPjQMk


I am a bit late but I found a solution on how to keep the value of a Provider alive after a Navigator.push() without having to put the Provider above the MaterialApp.

To do so, I have used the library custom_navigator. It allows you to create a Navigator wherever you want in the tree.

You will have to create 2 different GlobalKey<NavigatorState> that you will give to the MaterialApp and CustomNavigator widgets. These keys will allow you to control what Navigator you want to use.

Here is a small snippet to illustrate how to do

class App extends StatelessWidget {   GlobalKey<NavigatorState> _mainNavigatorKey = GlobalKey<NavigatorState>(); // You need to create this key for the MaterialApp too   @override   Widget build(BuildContext context) {      return MaterialApp(         navigatorKey: _mainNavigatorKey;  // Give the main key to the MaterialApp         home: Provider<bool>.value(            value: myProviderFunction(),            child: Home(),         ),      );   }}class Home extends StatelessWidget {   GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>(); // You need to create this key to control what navigator you want to use   @override   Widget build(BuildContext context) {      final bool myBool = Provider.of<bool>(context);      return CustomNavigator (         // CustomNavigator is from the library 'custom_navigator'         navigatorKey: _navigatorKey,  // Give the second key to your CustomNavigator         pageRoute: PageRoutes.materialPageRoute,         home: Scaffold(            body: FlatButton(               child: Text('Push'),               onPressed: () {                  _navigatorKey.currentState.push(  // <- Where the magic happens                     MaterialPageRoute(                        builder: (context) => SecondHome(),                     ),                  },               ),            ),         ),      );      }}class SecondHome extends StatelessWidget {   @override   Widget build(BuildContext context) {      final bool myBool = Provider.of<bool>(context);      return Scaffold(         body: FlatButton(            child: Text('Pop'),            onPressed: () {               Novigator.pop(context);            },         ),      );   }}

Here you can read the value myBool from the Provider in the Home widget but also ine the SecondHome widget even after a Navigator.push().

However, the Android back button will trigger a Navigator.pop() from the Navigator of the MaterialApp. If you want to use the CustomNavigator's one, you can do this:

// In the Home Widget insert this   ...   @override   Widget build(BuildContext context) {      return WillPopScope(         onWillPop: () async {            if (_navigatorKey.currentState.canPop()) {               _navigatorKey.currentState.pop();  // Use the custom navigator when available               return false;  // Don't pop the main navigator            } else {               return true;  // There is nothing to pop in the custom navigator anymore, use the main one            }         },         child: CustomNavigator(...),      );   }   ...