如何在 Flutter 中正确扩展自定义 Provider
How to correctly extend a custom Provider in Flutter
我有一个父级 ChangeNotifier ParentProvider
,另外 2 个提供商扩展了 ParentProvider
;
ChildProviderA
, ChildProviderB
.
我有一条路线叫做 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()
);
}
}
根据我想使用提供程序的参数,在任何一种情况下,我都想在 _Screen
小部件的 ParentProvider
中调用一个名为 initData()
的函数。
@override
Widget build(BuildContext context) {
...
Provider.of<ParentProvider>(context, listen: false).initData();
...
}
这给我一个错误
Error: Could not find the correct Provider<ParentProvider> above this _Screen Widget
如果我用Provider.of<ChildProviderA>(context, listen: false).initData();
或Provider.of<ChildProviderB>(context, listen: false).initData();
它有效,但我希望在使用的任何一个子 Provider 中都能调用 initData。
如何做到这一点?
Provider.of
查找具有完全给定类型的提供者。它不包括子类型。
如果子屏幕需要访问一些具有相同格式的不同数据,您可以在两种情况下使用相同的提供程序,通过构造函数将不同的数据传递给它:
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(),
);
}
}
如果您确实有两个不同的 ChangeNotifier 实现共享同一接口,您可以使用父类型提供和访问它们:
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(),
);
}
}
定义 children 提供程序时,请使用扩展。
此外,所有提供者都必须在 children 之上,并且在他们正在收听的同一路线中。您可以在定义 children 类 时尝试添加 extends ParentProvider。即
class ChildA extends ParentProvider {
//here you have access to methods in parent.
you can add a method here that triggers something form the parent.
void childMethod ()=> methodFromParentLikeInitData();
}
我有一个父级 ChangeNotifier ParentProvider
,另外 2 个提供商扩展了 ParentProvider
;
ChildProviderA
, ChildProviderB
.
我有一条路线叫做 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()
);
}
}
根据我想使用提供程序的参数,在任何一种情况下,我都想在 _Screen
小部件的 ParentProvider
中调用一个名为 initData()
的函数。
@override
Widget build(BuildContext context) {
...
Provider.of<ParentProvider>(context, listen: false).initData();
...
}
这给我一个错误
Error: Could not find the correct Provider<ParentProvider> above this _Screen Widget
如果我用Provider.of<ChildProviderA>(context, listen: false).initData();
或Provider.of<ChildProviderB>(context, listen: false).initData();
它有效,但我希望在使用的任何一个子 Provider 中都能调用 initData。
如何做到这一点?
Provider.of
查找具有完全给定类型的提供者。它不包括子类型。
如果子屏幕需要访问一些具有相同格式的不同数据,您可以在两种情况下使用相同的提供程序,通过构造函数将不同的数据传递给它:
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(),
);
}
}
如果您确实有两个不同的 ChangeNotifier 实现共享同一接口,您可以使用父类型提供和访问它们:
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(),
);
}
}
定义 children 提供程序时,请使用扩展。 此外,所有提供者都必须在 children 之上,并且在他们正在收听的同一路线中。您可以在定义 children 类 时尝试添加 extends ParentProvider。即
class ChildA extends ParentProvider {
//here you have access to methods in parent.
you can add a method here that triggers something form the parent.
void childMethod ()=> methodFromParentLikeInitData();
}