关于flutter的provider出现的错误
About errors that occur in flutter's provider
我正在学习 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:
我不会分离widgets,我想写一个类似code2的widget
有什么好的方法请告诉我。
谢谢!
在你的第一个例子中,NewWidget
是用一个新的 BuildContext
构建的,它已经可以访问它的祖先,所以这个 Widget 可以看到你在那里创建的提供者:context.read<Model>()
.
但是,在你的第二个例子中,你在同一个小部件 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
可用于检索有关您刚创建的提供商的信息,这是因为您的构建器小部件是在您的 ChangeNotifierProvider 之后构建,它是它的子级,因此它可以轻松地在其父级上查找并找到此信息。
还要注意错误告诉你的是什么,flutter 编译器在这类问题上真的很聪明:
Make sure that Main is under your MultiProvider/Provider. This
usually happen when you are creating a provider and trying to read it
immediatly.
这些行准确地告诉你我之前解释的内容。
除了上面的回答,还可以使用Provider包的Consumerclass
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';
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: Consumer<Model>(
builder: (context, model, _) {
return RaisedButton(
child: Text(
"test",
),
onPressed: () {
context.read<Model>().save();
},
);
},
),
),
);
}
}
从 MultiProvider 包装 MaterialApp。并设置 Provider Class(es) 的值。
例如:
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Cart(),
),
],
child: MaterialApp(
title: 'Perfumino',
home: Home(),
),
);
我正在学习 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:
我不会分离widgets,我想写一个类似code2的widget
有什么好的方法请告诉我。
谢谢!
在你的第一个例子中,NewWidget
是用一个新的 BuildContext
构建的,它已经可以访问它的祖先,所以这个 Widget 可以看到你在那里创建的提供者:context.read<Model>()
.
但是,在你的第二个例子中,你在同一个小部件 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
可用于检索有关您刚创建的提供商的信息,这是因为您的构建器小部件是在您的 ChangeNotifierProvider 之后构建,它是它的子级,因此它可以轻松地在其父级上查找并找到此信息。
还要注意错误告诉你的是什么,flutter 编译器在这类问题上真的很聪明:
Make sure that Main is under your MultiProvider/Provider. This usually happen when you are creating a provider and trying to read it immediatly.
这些行准确地告诉你我之前解释的内容。
除了上面的回答,还可以使用Provider包的Consumerclass
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';
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: Consumer<Model>(
builder: (context, model, _) {
return RaisedButton(
child: Text(
"test",
),
onPressed: () {
context.read<Model>().save();
},
);
},
),
),
);
}
}
从 MultiProvider 包装 MaterialApp。并设置 Provider Class(es) 的值。
例如:
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Cart(),
),
],
child: MaterialApp(
title: 'Perfumino',
home: Home(),
),
);