Why Hero doesn't work with Multiprovider?
As much as I understand I think your problem is also one of the typical ones while using providers.
I always recommend using provider at the root of your application (above MaterialApp), that is mainly the best way to use it without running into errors.
You see actually what is happening here, that providers work based on hierarchy (They provide a specific value to all widgets and sub-widgets you can say) and I'm sure you were also expecting this, But when we use a navigator instead of this parent child relation between widgets it is more of a Sibling-relation between pages. Note down I used the word pages here, Your provider for your case is only providing the value to the sub-widgets of that specific page where you used it, when you navigate to the new page that is now on the top of the navigation stack is not a sub-widget, rather it is sort of sibling relation and hence you cannot access the provider here.
If you do not understand this, do not worry simplest solution and visualization for this is just to open up dart dev tools on browser and in the Widgets Inspector, Check out the widget Hierarchy, you will observe that the widget where you want to use the value provided by the provider is not under that hierarchy, Now you only need to figure out what you should do to make it happen.
One solution I can give is just to Use the provider at the root of application (Above MaterialApp).
Ricky
Updated on December 01, 2022Comments
-
Ricky over 1 year
I have a list of cards. When I tap a card, the BoxViewPage opens.
If I use Hero and Multiprovider together, I get an error,
but,
if I use Hero and MultiProvider individually everything works correctly
Why?
List of Cards:
return Hero( tag: box.ID, child: InkWell( child: selectBoxSize(viewType), onTap: () async { Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) => MultiProvider( providers: [ ChangeNotifierProvider<Archive>.value(value: archive), ChangeNotifierProvider<Box>.value(value: box), ], builder: (context, child) => BoxViewPage(), ), ),
Inside BoxViewPage:
class BoxCardView extends StatefulWidget { const BoxCardView({Key key}) : super(key: key); @override _BoxCardViewState createState() => _BoxCardViewState(); } class _BoxCardViewState extends State<BoxCardView> { @override Widget build(BuildContext context) { final box = Provider.of<Box>(context); return Hero( tag: box.ID, child: Card( clipBehavior: Clip.antiAlias, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.0), ), margin: EdgeInsets.all(12), child: Column( children: <Widget>[ Expanded(child: WidgetEditPhotosScrollHoriz()), WidgetNameDescrTagsEdit(), ], ), ), ); } }
Error:
Si è verificata un'eccezione ProviderNotFoundException (Error: Could not find the correct Provider above this WidgetEditPhotosScrollHoriz Widget
This happens because you used a
BuildContext
that does not include the provider of your choice. There are a few common scenarios:-
You added a new provider in your
main.dart
and performed a hot-reload. To fix, perform a hot-restart. -
The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then other routes will not be able to access that provider.
-
You used a
BuildContext
that is an ancestor of the provider you are trying to read.Make sure that WidgetEditPhotosScrollHoriz is under your MultiProvider/Provider. This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
Widget build(BuildContext context) { return Provider<Example>( create: (_) => Example(), // Will throw a ProviderNotFoundError, because `context` is associated // to the widget that is the parent of `Provider<Example>` child: Text(context.watch<Example>()), ), }
consider using
builder
like so:Widget build(BuildContext context) { return Provider<Example>( create: (_) => Example(), // we use `builder` to obtain a new `BuildContext` that has access to the provider builder: (context) { // No longer throws return Text(context.watch<Example>()), } ), }
If none of these solutions work, consider asking for help on StackOverflow: https://stackoverflow.com/questions/tagged/flutter )
-
Felipe Morschel about 2 yearsAre you using provider inside the
WidgetEditPhotosScrollHoriz
? -
Mahdi Arabpour about 2 yearsdo you use a
Navigator
widget anywhere in your widget tree? -
Ricky about 2 yearsYes, I use Navigator to change pages and normally I put the MultiProvider Builder inside the Navigator.Push method
-
Mahdi Arabpour about 2 yearsNo I mean a custom 'Navigator' widget in widget tree!
-
Ricky about 2 yearsno, any custom 'Navigator'
-
Jodeveloper8 about 2 years
-
-
Ricky about 2 yearsif I put provider Above MaterialApp, Hero works, but I need to change values of provider during the navigation in other pages so I can't put it above Material App
-
KaZami-Ryu about 2 yearsyou can create your own custom class which stores the value then create a method to set and get its value (also use notifylistners after inherting it from ChangeNotifier class), And you can use provider for that new custom class now.