【问题标题】:Bloc: is it possible to yield 2 time the same state?Bloc:是否有可能产生 2 次相同的状态?
【发布时间】:2019-11-12 23:55:42
【问题描述】:

在登录视图中,如果用户在未插入凭据的情况下点击登录按钮,则 LoginFailState 为 yield 并且视图会对此做出反应。如果他再次点击,此 LoginFailstate 再次为 yield,但视图不会对此做出反应。那么,有没有办法让相同的状态产生更多倍?

有一些代码可以更好地解释我的情况:

class LoginBloc extends Bloc<LoginEvent, LoginState> {
  @override
  LoginState get initialState => LoginUninitialized();

  @override
  Stream<LoginState> mapEventToState(LoginEvent event) {
    if (event is loginButtonPressed) {
      yield LoginFailState();
    }
  }

查看:

 @override
  Widget build(BuildContext context) {
    return BlocBuilder(
      bloc: _loginBloc,
      builder: (BuildContext context, LoginState state) {
    if (state is LoginFail) {
        print ('Login fail');
    }
    return Column(
          ...
    )

【问题讨论】:

    标签: flutter state handle bloc


    【解决方案1】:

    一种较晚的解决方法是向状态get props 添加一个随机双精度,这样状态就不会相等,如果需要,您可以一个接一个地产生它们。 另外,Random().nextDouble() 的复杂度是 O(1),所以你不必担心性能

    class LoginFailState extends LoginState {
      @override
      List<Object> get props => [Random().nextDouble()];
    }
    

    【讨论】:

      【解决方案2】:

      如果您使用 Equitable 并尝试发出具有不同属性的同一 State 的两个相等实例,请确保覆盖 props 数组。通过覆盖props 数组,Equitable 将知道如何比较状态实例。

       class TablesLoadedState extends Equatable {
        final List<TableEntity> tablesList;
      
        TablesLoadedState(this.tablesList);
      
        @override
        List<Object> get props => [tablesList];
      }
      

      因此,当 bloc 发出两个具有不同值的相同状态的实例时,这些状态实例将被传递给 BlocListener 并且 UI 将根据新数据进行更新。

      【讨论】:

      • 谢谢,这应该是正确答案
      【解决方案3】:

      如果您不扩展 Equitable,或者实现您自己的 '==' 逻辑以使两个 LoginFailStates 相等,您可以接收“相同”状态的更新。

      解决方案是在两者之间产生不同的状态,就像在 Bloc 示例中一样。

      yield LoginLoading();
      

      每次点击登录按钮时都会调用它。 Felangel's LoginBloc example.

      【讨论】:

        【解决方案4】:

        默认情况下,当相同的状态一个接一个地传递时,BLoC 模式不会发出状态。一种方法是在传递 LoginFailState 之后传递您的初始 BLoC 状态。

        所以在用户点击带有错误凭据的按钮后,传递的状态将不会是:

        LoginFailState()
        LoginFailState()
        

        但是

        LoginFailState()
        LoginEmptyState()
        LoginFailState()
        LoginEmptyState()
        

        这将使 UI 对它们中的每一个做出反应。

        但我认为最好和最干净的解决方案是在通过 LoginFailState() 之前从 BLoC 传递 LoadingState

        你可以关注我最近写的关于这个话题的blog post

        【讨论】:

        • 谢谢,我被这个问题搞疯了!没有找到任何其他解决方案。
        【解决方案5】:

        使用 BlocListener 对状态变化做出反应。

            BlocListener(
              bloc: _loginBloc,
              listener: (BuildContext context, LoginState state) {
                if (state is LoginFail) {
                  print('Login failed');
                  // Or show a Snackbar
                }
              },
              child: BlocBuilder(
                bloc: _loginBloc,
                builder: (BuildContext context, LoginState state){
                  // Your display code here
                  return Container();
                },
              ),
            )
        

        【讨论】:

        • BlocListener 甚至不会调用,如果“相同”状态产生两次,因为它不会被发出。
        猜你喜欢
        • 2019-11-26
        • 2021-01-28
        • 2020-07-20
        • 2020-07-08
        • 2021-10-29
        • 2020-10-03
        • 2023-03-17
        • 2021-09-17
        • 2015-07-07
        相关资源
        最近更新 更多