问题描述
我无法通过FloatingActionButton中的showModalBottomSheet访问在脚手架上方定义的提供程序。
我已经这样定义了主页:
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
);
}
)
}
}
这是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);
)
],);
}
);
}
}
错误:在此BottomSheet小部件上方找不到正确的提供者
解决方法
这是由于传递了错误的上下文引起的。将FAB包装到Builder窗口小部件,并将其作为builder属性传递。这将需要一个新的上下文并将其传递给showModalBottomSheet。另外,您可以进行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)
};
)
],);
}
);
}
}
,
解决方案
首页:
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => MyProvider(),// here is the problem
);
}
)
}
}
MyFAB:
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);
)
],);
}
);
}
}
,
通过将提供者置于 MaterialApp
之上来修复,如 here 所述。
在材质应用的根目录下创建底部工作表。如果在材料应用程序下声明了一个提供者,则底部工作表无法访问它,因为提供者不是小部件树中底部工作表的祖先。
下面的屏幕截图显示了一个小部件树:整个应用程序在 Wrapper
内,底部工作表不是在 Wrapper
内创建的。它被创建为 MaterialApp
的另一个子元素(在本例中具有根元素 Container
)。
对于您的情况:
// main.dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => MyProvider(),_) {
return MaterialApp(
home: HomePage(),);
},);
}
}
// home_page.dart
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: MyFAB()
);
}
}