无法显示 SnackBar

25 浏览
0 Comments

无法显示 SnackBar

我是Flutter的新手,只是为了理解这个框架的工作原理而玩一下。所以下面的代码没有太多意义。

我想在应用程序加载时调用一个子小部件来显示一个snack bar。

以下是代码:

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): GetSnackBarWidget(dirty)构建期间调用了setState()或markNeedsBuild()。

I/flutter ( 3781): 由于框架已经在构建小部件的过程中,因此无法将此Scaffold小部件标记为需要构建。

I/flutter ( 3781): 只有在某个祖先小部件当前正在构建时,才能在构建阶段将小部件标记为需要构建。这种情况下允许抛出此异常,因为框架

I/flutter ( 3781): 在构建子小部件之前会先构建父小部件,这意味着脏的后代小部件总是会被构建。

I/flutter ( 3781): 否则,在此构建阶段框架可能不会访问此小部件。

I/flutter ( 3781): 在调用setState()或markNeedsBuild()的小部件是:

I/flutter ( 3781): Scaffold(dependencies: [_LocalizationsScope-[GlobalKey#33728], Directionality, _InheritedTheme,

I/flutter ( 3781): MediaQuery], state: ScaffoldState#dbc9e(tickers: tracking 2 tickers))

I/flutter ( 3781): 在进行有问题调用时正在构建的小部件是:

I/flutter ( 3781): GetSnackBarWidget(dirty)

有人可以详细解释一下发生了什么吗?

0
0 Comments

"Unable to display SnackBar"问题的原因是在构建小部件时直接调用Scaffold.of(context).showSnackBar(snackBar)。如果有一个按钮,可以将其用作onPressed方法,因为它不会立即被调用,而是在某些其他异步事件之后。

解决方法是,如果一开始就要显示snackbar,则可以告诉应用程序在构建所有小部件完成后立即显示snackbar。可以使用WidgetsBinding.instance.addPostFrameCallback()添加一个回调方法来显示snackbar,如下所示:

final GlobalKey _scaffoldKey = GlobalKey();

...

return Scaffold(

key: _scaffoldKey,

...

//在构建方法中想要显示snackbar时,使用addPostFrameCallback

WidgetsBinding.instance.addPostFrameCallback((_) => _showMessage('snackbar message'));

...

void _showMessage(String message) {

_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(message),));

}

这个解决方法有效。如果我理解正确的话,问题是我在调用仍处于构建状态的小部件(Scaffold)。此外,你能否提供一些详细解释WidgetsBinding.instance.addPostFrameCallback和_scaffoldKey.currentState的链接。我尝试过很多搜索但没有找到。谢谢。

这里有一个类似的例子-stackoverflow.com/questions/51458885/…,这可能是我最初得到答案的地方。

0
0 Comments

无法显示SnackBar的原因是在上述示例中,Scaffold.of()调用了一个不包含Scaffold的上下文。解决方法是将Builder包装在Scaffold中。以下是修复后的代码示例:

class _DelayWidgetState extends State {

Widget build(BuildContext context) {

return new Scaffold(

appBar: new AppBar(

title: new Text("SbackBar功能"),

),

body: new Scaffold(

body: new Builder(builder: (BuildContext context) {

return new RaisedButton(

onPressed: () {

Scaffold.of(context).showSnackBar(

new SnackBar(

content: new Text("发送消息"),

),

);

},

child: new Text("点击"),

);

}),

),

);

}

}

0
0 Comments

首先,将SnackBar放在build()方法中是一个不好的做法。你可以尝试下面的解决方案,在应用启动时显示SnackBar,正如你所需要的那样。

class _HomePageState extends State {

GlobalKey _key = GlobalKey();

void initState() {

super.initState();

Timer.run(() => _key.currentState.showSnackBar(SnackBar(content: Text("Hi"),)));

}

Widget build(BuildContext context) {

return Scaffold(

key: _key,

appBar: AppBar(title: Text("App")),

body: Container(),

);

}

}

在这个解决方案中,我们创建了一个GlobalKey对象来控制Scaffold的状态。然后,在initState()方法中,我们使用Timer.run()方法来在应用启动后立即显示SnackBar。最后,在build()方法中,我们将_scaffoldKey与Scaffold小部件关联起来。

这样,当应用启动时,SnackBar将立即显示出来,而不是等待build()方法被调用。这解决了无法显示SnackBar的问题,并确保SnackBar在应用启动时立即显示出来。

0