在Flutter中,当流的值更改时,我怎么称呼Navigator.push?我已经尝试了下面的代码,但出现错误。
StreamBuilder(
stream: bloc.streamValue,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
if (snapshot.hasData && snapshot.data == 1) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SomeNewScreen()),
);
}
return Text("");
});
答案 0 :(得分:12)
您不应使用StreamBuilder
来处理导航。
StreamBuilder
用于构建屏幕内容,而无其他内容。
相反,您将必须收听流以手动触发副作用。这是通过使用StatefulWidget
并覆盖initState
/ dispose
来完成的:
class Example extends StatefulWidget {
final Stream<int> stream;
const Example({Key key, this.stream}) : super(key: key);
@override
ExampleState createState() => ExampleState();
}
class ExampleState extends State<Example> {
StreamSubscription _streamSubscription;
@override
void initState() {
super.initState();
_listen();
}
@override
void didUpdateWidget(Example oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.stream != widget.stream) {
_streamSubscription.cancel();
_listen();
}
}
void _listen() {
_streamSubscription = widget.stream.listen((value) {
Navigator.pushNamed(context, '/someRoute/$value');
});
}
@override
void dispose() {
_streamSubscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
请注意,如果您使用InheritedWidget
获取流(通常是BLoC),则将要使用didChangeDependencies
而不是initState
/ didUpdateWidget
。 / p>
这导致:
class Example extends StatefulWidget {
@override
ExampleState createState() => ExampleState();
}
class ExampleState extends State<Example> {
StreamSubscription _streamSubscription;
Stream _previousStream;
void _listen(Stream<int> stream) {
_streamSubscription = stream.listen((value) {
Navigator.pushNamed(context, '/someRoute/$value');
});
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
final bloc = MyBloc.of(context);
if (bloc.stream != _previousStream) {
_streamSubscription?.cancel();
_previousStream = bloc.stream;
_listen(bloc.stream);
}
}
@override
void dispose() {
_streamSubscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
答案 1 :(得分:1)
您可以使用以下自定义侦听器扩展StreamBuilder
:
typedef StreamListener<T> = void Function(T value);
class StreamListenableBuilder<T> extends StreamBuilder<T> {
final StreamListener<T> listener;
const StreamListenableBuilder({
Key key,
T initialData,
Stream<T> stream,
@required this.listener,
@required AsyncWidgetBuilder<T> builder,
}) : super(key: key, initialData: initialData, stream: stream, builder: builder);
@override
AsyncSnapshot<T> afterData(AsyncSnapshot<T> current, T data) {
listener(data);
return super.afterData(current, data);
}
}
然后以这种方式连接侦听器:
StreamBuilder(
stream: bloc.streamValue,
listener: (value) {
if (value==1) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SomeNewScreen()),
);
}
},
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
return Container();
});