Flutter BLoC模式 - 如何在流事件后导航到另一个屏幕?

25

我关注的问题是在BLoC模式中使用的导航(navigation)

在我的LoginScreen小部件中,我有一个按钮,用于将事件添加到bloc的EventSink中。 bloc调用API并验证用户身份。 在LoginScreen小部件中,我在哪里监听流,并在成功返回状态后如何导航到另一个屏幕?


1
我猜你可以在 initState 中监听它,并根据流的结果使用 Navigator.push() 进行导航。 - nonybrighto
重复的问题 https://dev59.com/p1UK5IYBdhLWcg3wwSLg 请查看我对该问题的回答。 - boformer
@boformer,我看到了你的回复,但我无法完全理解它。你是在使用InheritedWidget来访问bloc吗?你有任何GitHub仓库可以让我查看完整的代码吗?感谢你的回答。 - Sebastian
1
我认为这个答案正是你想要的:https://dev59.com/xq7la4cB1Zd3GeqPYCV_#52167972 - Mantoska
1
可能是 Right way to handle navigation using BLoC 的重复问题。 - Pablo Cegarra
显示剩余7条评论
4个回答

11

使用BlockListener

 BlocListener(
  bloc: _yourBloc,
  listener: (BuildContext context, YourState state) {
    if(state is NavigateToSecondScreen){
      Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {return SecondScreen();}));
    }
  },
  child: childWidget
)

7
导航器在blocBuilder中无法工作,因为在blocBuilder中,您只能返回一个小部件。BlocListener解决了我的问题。
添加此代码:
BlocListener(
  bloc: _yourBloc,
  listener: (BuildContext context, YourState state) {
    if(state is NavigateToSecondScreen){
      Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {return SecondScreen();}));
    }
  },
  child: childWidget
)

5
首先:如果没有业务逻辑,那么就不需要去YourBloc类。
但是有时候需要一些用户活动来执行Bloc类中的一些逻辑,然后Bloc类必须决定接下来要做什么:仅重建小部件、显示对话框甚至导航到下一个路由。在这种情况下,您必须向UI发送一些状态以完成操作。
然后又出现了另一个问题:当Bloc发送状态以显示toast时,我该怎么处理小部件?
这就是整个故事的主要问题。
许多答案和文章建议使用flutter_block。这个库有BlocBuilderBlocListener。通过这些类,您可以解决一些问题,但不是全部。
在我的情况下,我使用了BlocConsumer,它管理BlocBuilderBlocListener,提供了一个出色的方式来管理状态。
从文档中可以看到:
BlocConsumer<BlocA, BlocAState>(
  listenWhen: (previous, current) {
    // Return true/false to determine whether or not
    // to invoke listener with state
  },
  listener: (context, state) {
    // Do stuff here based on BlocA's state
  },
  buildWhen: (previous, current) {
    // Return true/false to determine whether or not
    // to rebuild the widget with state
  },
  builder: (context, state) {
    // Return widget here based on BlocA's state
  }
)

正如您可以从BlocConsumer中看到的那样,您可以过滤状态:您可以轻松地定义状态以重建小部件并显示一些弹出窗口或导航到下一个屏幕。

0

类似这样:

if (state is PhoneLoginCodeSent) {
    // Dispatch here to reset PhoneLoginFormState
    SchedulerBinding.instance.addPostFrameCallback((_) {
        Navigator.of(context).push(
            MaterialPageRoute(
                builder: (context) {
                    return VerifyCodeForm(phoneLoginBloc: _phoneLoginBloc);
                },
            ),
        );
        return;
    });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接