![](/img/trans.png)
[英]Flutter can't preserve stateful state when exit showModalBottomSheet and show showModalBottomSheet again
[英]Flutter: can't access Provider from showModalBottomSheet
我无法从 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 小部件上方找到正确的 Provider<MyProvider。
通过将提供者置于MaterialApp
上来修复,如here所述。
底部工作表是在材料应用程序的根部创建的。 如果在材料应用程序下方声明了一个提供者,则底部工作表无法访问它,因为提供者不是小部件树中底部工作表的祖先。
下面的屏幕截图显示了一个小部件树:整个应用程序都在Wrapper
内部,底部工作表不是在Wrapper
内部创建的。 它被创建为MaterialApp
另一个子元素(在本例中为根元素Container
)。
对于您的情况:
// 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()
);
}
}
这是由于将错误的上下文传递给它造成的。 将您的 FAB 包装到 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(),
builder: (context, _) {
return Scaffold(
body: Consumer<MyProvider>(
builder: (context, provider, _) {
return Text(provider.mytext); // this works fine
}
),
floatingActionButton: MyFAB(context), // here is the problem
);
}
)
}
}
我的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.