我是Flutter的新手,只是四处逛逛以了解此框架的工作原理。因此,下面的代码没有多大意义。
我正在尝试通过调用子小部件来在应用加载后立即显示小吃店。
这是代码:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Demo')),
body: GetSnackBarWidget(),
),
);
}
}
class GetSnackBarWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final snackBar = SnackBar(content: Text("SnackBar"));
Scaffold.of(context).showSnackBar(snackBar);
return Text("returned");
}
}
但是我收到以下异常:
I/flutter ( 3781): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 3781): The following assertion was thrown building GetSnackBarWidget(dirty):
I/flutter ( 3781): setState() or markNeedsBuild() called during build.
I/flutter ( 3781): This Scaffold widget cannot be marked as needing to build because the framework is already in the
I/flutter ( 3781): process of building widgets. A widget can be marked as needing to be built during the build phase
I/flutter ( 3781): only if one of its ancestors is currently building. This exception is allowed because the framework
I/flutter ( 3781): builds parent widgets before children, which means a dirty descendant will always be built.
I/flutter ( 3781): Otherwise, the framework might not visit this widget during this build phase.
I/flutter ( 3781): The widget on which setState() or markNeedsBuild() was called was:
I/flutter ( 3781): Scaffold(dependencies: [_LocalizationsScope-[GlobalKey#33728], Directionality, _InheritedTheme,
I/flutter ( 3781): MediaQuery], state: ScaffoldState#dbc9e(tickers: tracking 2 tickers))
I/flutter ( 3781): The widget which was currently being built when the offending call was made was:
I/flutter ( 3781): GetSnackBarWidget(dirty)
有人可以详细解释发生了什么事吗?
答案 0 :(得分:0)
基本上,在构建窗口小部件时,不能直接调用Scaffold.of(context).showSnackBar(snackBar)。如果有按钮,则可以将其用于onPressed方法,因为在构建窗口小部件时不会立即调用它,而是在其他一些异步事件之后调用它。
如果您有一个快餐栏可以立即显示,则解决方案是告诉应用程序在构建完所有小部件后立即显示快餐栏。您可以通过使用WidgetsBinding.instance.addPostFrameCallback()来添加显示小吃店的回调方法来做到这一点,就像这样:
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
...
return Scaffold(
key: _scaffoldKey,
...
//when you want to display the snackbar during a build method,
//use addPostFrameCallback
WidgetsBinding.instance.addPostFrameCallback((_) => _showMessage('snackbar message'));
...
void _showMessage(String message) {
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(message),));
}
答案 1 :(得分:0)
首先,将SnackBar
放入您的build()
方法中不是一个好主意。您可以尝试根据需要在应用启动时显示SnackBar
的解决方案。
class _HomePageState extends State<HomePage> {
GlobalKey<ScaffoldState> _key = GlobalKey();
@override
void initState() {
super.initState();
Timer.run(() => _key.currentState.showSnackBar(SnackBar(content: Text("Hi"),)));
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _key,
appBar: AppBar(title: Text("App")),
body: Container(),
);
}
}
答案 2 :(得分:0)
如果要在小部件中显示SnackBar,则必须遵循以下代码:
class _DelayWidgetState extends State<DelayWidget> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("SbackBar Functionality"),
),
body: new Builder(builder: (BuildContext context) {
return new RaisedButton(
onPressed: () {
Scaffold.of(context).showSnackBar(
new SnackBar(
content: new Text("Sending Message"),
),
);
},
child: new Text("Click"),
);
}),
);
}
}
在上面的示例中,添加的另一个Builder作为Scaffold.of()调用,其上下文不包含Scaffold。