[英]Flutter: can't access Provider from showModalBottomSheet
I can't access a provider defined above a Scaffold from showModalBottomSheet in the FloatingActionButton.我无法从 FloatingActionButton 中的 showModalBottomSheet 访问在脚手架上方定义的提供程序。
I've defined a HomePage like so:我像这样定义了一个主页:
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => MyProvider(),
builder: (context, _) {
return Scaffold(
body: Consumer<MyProvider>(
builder: (context, provider, _) {
return Text(provider.mytext); // this works fine
}
),
floatingActionButton: MyFAB(), // here is the problem
);
}
)
}
}
And this is MyFAB:这是 MyFAB:
class MyFAB extends StatefulWidget {
@override
_MyFABState createState() => _MyFABState();
}
class _MyFABState extends State<MyFAB> {
@override
Widget build(BuildContext context) {
return FloatingActionButton(
...
onPressed: () => show(),
);
}
void show() {
showModalBottomSheet(
...
context: context,
builder: (BuildContext context) {
return Wrap(
children: [
...
FlatButton(
onPressed: Provider.of<MyProvider>(context, listen: false).doSomething(); //Can't do this
Navigator.pop(context);
)
],
);
}
);
}
}
Error: Could not find the correct Provider<MyProvider above this BottomSheet Widget.错误:无法在此 BottomSheet 小部件上方找到正确的 Provider<MyProvider。
Fixed by placing the provider above MaterialApp
, as described here .通过将提供者置于
MaterialApp
上来修复,如here所述。
Bottom sheets are created at the root of the material app.底部工作表是在材料应用程序的根部创建的。 If a prodiver is declared below the material app, a bottom sheet cannot access it because the provider is not an ancestor of the bottom sheet in the widget tree.
如果在材料应用程序下方声明了一个提供者,则底部工作表无法访问它,因为提供者不是小部件树中底部工作表的祖先。
The screenshot below shows a widget tree: the whole app is inside Wrapper
and the bottom sheet is not created inside Wrapper
.下面的屏幕截图显示了一个小部件树:整个应用程序都在
Wrapper
内部,底部工作表不是在Wrapper
内部创建的。 It is created as another child of MaterialApp
(with a root element Container
in this case).它被创建为
MaterialApp
另一个子元素(在本例中为根元素Container
)。
For your case:对于您的情况:
// main.dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => MyProvider(),
builder: (context, _) {
return MaterialApp(
home: HomePage(),
);
},
);
}
}
// home_page.dart
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: MyFAB()
);
}
}
This is caused by passing it the wrong context.这是由于将错误的上下文传递给它造成的。 Wrap your FAB to a Builder widget and pass it as builder property.
将您的 FAB 包装到 Builder 小部件并将其作为构建器属性传递。 This will take a new context and pass it to showModalBottomSheet.
这将采用一个新的上下文并将其传递给 showModalBottomSheet。 Also, you can do
onPressed: show
, it's more concise.另外,你可以做
onPressed: show
,它更简洁。
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => MyProvider(),
builder: (context, _) {
return Scaffold(
body: Consumer<MyProvider>(
builder: (context, provider, _) {
return Text(provider.mytext); // this works fine
}
),
floatingActionButton: MyFAB(context), // here is the problem
);
}
)
}
}
class MyFAB extends StatefulWidget {
@override
_MyFABState createState() => _MyFABState();
}
class _MyFABState extends State<MyFAB> {
@override
Widget build(BuildContext context) {
return FloatingActionButton(
...
onPressed: (context) => show(context),
);
}
void show(ctx) {
showModalBottomSheet(
...
context: ctx,
builder: (BuildContext context) {
return Wrap(
children: [
...
FlatButton(
onPressed: () {
Provider.of<MyProvider>(ctx, listen: false).doSomething(); //Can't do this
Navigator.pop(ctx)
};
)
],
);
}
);
}
}
SOLUTION解决方案
HomePage:主页:
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => MyProvider(),
builder: (context, _) {
return Scaffold(
body: Consumer<MyProvider>(
builder: (context, provider, _) {
return Text(provider.mytext); // this works fine
}
),
floatingActionButton: MyFAB(context), // here is the problem
);
}
)
}
}
MyFAB:我的FAB:
class MyFAB extends StatefulWidget {
final BuildContext ctx;
MyFAB(this.ctx)
@override
_MyFABState createState() => _MyFABState();
}
class _MyFABState extends State<MyFAB> {
@override
Widget build(BuildContext context) {
return FloatingActionButton(
...
onPressed: () => show(),
);
}
void show() {
showModalBottomSheet(
...
context: context,
builder: (BuildContext context) {
return Wrap(
children: [
...
FlatButton(
onPressed: Provider.of<MyProvider>(widget.ctx, listen: false).doSomething(); //Can't do this
Navigator.pop(context);
)
],
);
}
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.