一旦SnackBar
的Stream
发送新的String
,我想展示String
。
我试图在StreamBuilder
中放置一个StatefulWidget
,以便能够调用Scaffold.of()
(因为它现在是另一个context
)。但后来我收到这个错误:
抛出以下断言构建StreamBuilder(dirty,state:_StreamBuilderBaseState>#7f258):在构建期间调用setState()或markNeedsBuild()。此Scaffold窗口小部件无法标记为需要构建,因为框架已在构建窗口小部件的过程中。只有当其中一个祖先正在构建时,才能将窗口小部件标记为需要在构建阶段构建。允许此异常,因为框架在子项之前构建父窗口小部件,这意味着将始终构建脏后代。否则,在此构建阶段,框架可能不会访问此窗口小部件。调用setState()或markNeedsBuild()的小部件是:Scaffold(依赖项:[_ LocalocalScope- [GlobalKey#0e1f6],Directionality,_InheritedTheme,MediaQuery],状态:ScaffoldState#3f2aa(代码:跟踪2代码))小部件在进行违规调用时正在构建的是:StreamBuilder(dirty,state:_StreamBuilderBaseState>#7f258)
我怎么解决这个问题?
这是一个显示问题的简单代码段:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: TestHome(),
);
}
}
class TestHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamSnackbar(),
);
}
}
class StreamSnackbar extends StatefulWidget {
@override
_StreamSnackbarState createState() => _StreamSnackbarState();
}
class _StreamSnackbarState extends State<StreamSnackbar> {
final status = StreamController<String>();
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () {
status.add('Test');
},
child: Text('Press me to trigger the Snackbar!'),
),
StreamBuilder<String>(
stream: status.stream,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text(snapshot.data)));
}
return Container(
height: 0,
width: 0,
); // just because we need to return a Widget
},
),
],
),
),
);
}
}
没有必要使用StreamBuilder
。无论如何,显示SnackBar
必须在同步build()
执行之外完成。
@override
void initState() {
super.initState();
status.stream.forEach((e) =>
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text(e))));
}
@override
void dispose() {
status.close();
super.dispose();
}