我正在了解flutter的提供者,并且遇到一个错误。
以下代码有效。
[code1]
class Model extends ChangeNotifier {
void save() {
print('save');
}
}
class Main extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Model(),
child: Scaffold(
appBar: AppBar(
title: Text('test'),
),
body: NewWidget(),
),
);
}
}
class NewWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
child: Text(
"test",
),
onPressed: () {
context.read<Model>().save();
},
);
}
}
但是下面的代码不起作用。
[code2]
class Model extends ChangeNotifier {
void save() {
print('save');
}
}
class Main extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Model(),
child: Scaffold(
appBar: AppBar(
title: Text('test'),
),
body: RaisedButton(
child: Text(
"test",
),
onPressed: () {
context.read<Model>().save();
},
),
),
);
}
}
使用此代码,按下按钮时输出以下错误。
Error: Could not find the correct Provider<Model> above this Main Widget
This likely happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
- 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 Main is under your MultiProvider/Provider<Model>.
This usually happen when you are creating a provider and trying to read it immediatly.
For example, instead of:
我不分离小部件,我想编写一个像code2这样的小部件。如果有什么好办法,请告诉我。
谢谢!
在您的第一个示例中,NewWidget
是使用新的BuildContext
构建的,并且已经可以访问其祖先,因此此小部件可以看到您在其中创建的提供者:context.read<Model>()
。
但是,在第二个示例中,您正在同一Widget Main
中创建和使用提供程序,因此所有内容都在同一BuildContext
上,并且当您运行context.read<Model>()
时,flutter会尝试在Widget树中查找找到Model
,但找不到,因为您刚刚创建了它。在这种情况下,您可以使用Builder小部件:
class Main extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Model(),
child: Scaffold(
appBar: AppBar(
title: Text('test'),
),
body: Builder(
// Here the magic happens
// this builder function will generate a new BuilContext for you
builder: (BuildContext newContext){
return RaisedButton(
child: Text(
"test",
),
onPressed: () {
newContext.read<Model>().save();
},
);
}
),
),
);
}
}
通过使用Builder
小部件,您可以创建新的BuildContext
,可用于检索有关刚创建的提供程序的信息,这是因为您的Builder小部件是在ChangeNotifierProvider之后生成的,并且是它的子项,因此可以轻松地在其父项中查找并找到此信息。
还请注意哪些错误会告诉您,Flutter编译器确实很聪明,可以解决此类问题:
请确保Main在您的MultiProvider / Provider之下。这个 通常在创建提供程序并尝试读取它时发生 立即。
这些行告诉您我之前所解释的。