How to correctly extend a custom Provider in Flutter
Provider.of
looks for provider with exactly given type. It doesn't include child types.
If the child screen needs to access some different data having same format, you can use the same provider in both cases passing it different data through constructor:
class MyScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (condition) {
return ChangeNotifierProvider(
create: (context) => ParentProvider(data1),
child: _Screen(),
);
}
return ChangeNotifierProvider(
create: (context) => ParentProvider(data2),
child: _Screen(),
);
}
}
If you really have two different ChangeNotifier implementations sharing same interface, you can provide and access them using parent type:
class MyScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (condition) {
return ChangeNotifierProvider<ParentProvider>(
create: (context) => ChildProviderA(),
child: _Screen(),
);
}
return ChangeNotifierProvider<ParentProvider>(
create: (context) => ChildProviderB(),
child: _Screen(),
);
}
}
Ismaeel Sherif
Updated on December 31, 2022Comments
-
Ismaeel Sherif over 1 year
I have a parent ChangeNotifier
ParentProvider
, and 2 other providers extend theParentProvider
;ChildProviderA
,ChildProviderB
.I have a route which is called
MyScreen
class MyScreen extends StatelessWidget { @override Widget build(BuildContext context) { if(ModalRoute.of(context).settings.arguments != null){ return ChangeNotifierProvider( create: (context) => ChildProviderA(), child: _Screen() ); } return ChangeNotifierProvider( create: (context) => ChildProviderB(), child: _Screen() ); } }
depending on the arguments I want to use a provider, and in either case, I want to call a function called
initData()
in theParentProvider
from the_Screen
widget.@override Widget build(BuildContext context) { ... Provider.of<ParentProvider>(context, listen: false).initData(); ... }
This gives me an error
Error: Could not find the correct Provider<ParentProvider> above this _Screen Widget
If I used
Provider.of<ChildProviderA>(context, listen: false).initData();
or
Provider.of<ChildProviderB>(context, listen: false).initData();
It works, but I want in either child Provider used, to be able to call initData.How can this be done ?
-
Ismaeel Sherif over 2 yearsthis is what I have done, but it doesn't work
-
Huthaifa Muayyad over 2 yearsYou need to put all of them above your widget.
-
Ismaeel Sherif over 2 yearsThe second example works. It still needed to declare an empty method in the ParentProvider to be able to run it from ChildA, but anyway it saved a lot of code
-
Ismaeel Sherif over 2 yearsdo you mean I should use the 3 providers in the route ?
-
Pavel over 2 yearsTo avoid empty methods in parent change notifier, you can make the parent class abstract and declare abstract method
-
Pavel over 2 years@HuthaifaMuayyad
Provider.of
usesgetElementForInheritedWidgetOfExactType
which doesn't look for subtypes, only exact given type -
Ismaeel Sherif over 2 years@Huthaifa I think I understood your solution, but it will contain a lot of extra functions in both child classes which just points to parent functions