当BLOC中的流值更改时导航到新屏幕 [英] Navigating to a new screen when stream value in BLOC changes

查看:92
本文介绍了当BLOC中的流值更改时导航到新屏幕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Flutter中,当流的值更改时,我将如何调用Navigator.push?我已经尝试了下面的代码,但出现错误.

In Flutter how would I call Navigator.push when the value of a stream changes? I have tried the code below but get an error.

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("");
        });

推荐答案

您不应使用StreamBuilder来处理导航. StreamBuilder用于构建屏幕内容,而无其他内容.

You should not use StreamBuilder to handle navigation. StreamBuilder is used to build the content of a screen and nothing else.

相反,您将必须收听流以手动触发副作用.这是通过使用StatefulWidget并像这样覆盖initState/dispose来完成的:

Instead, you will have to listen to the stream to trigger side-effects manually. This is done by using a StatefulWidget and overriding initState/dispose as such:

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.


Note that if you're using an InheritedWidget to obtain your stream (typically BLoC), you will want to use didChangeDependencies instead of initState/didUpdateWidget.

这导致:

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();
  }
}

这篇关于当BLOC中的流值更改时导航到新屏幕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆