在Dart(Flutter)中将两个“yield”放在一起,只执行第二次

问题描述 投票:2回答:1

在Flutter中,我使用BLoC模式和Firebase创建了一个登录/注册页面。注册用户后,我发送验证邮件并将状态更改为“VerificationEmailSentState”(因此我可以在PageView中显示SnackBar并切换到Login页面),然后将其重新更改为初始状态(InitialState)。问题是它直接跳转到InitialState而没有通过VerificationEmailSentState,因此没有显示SnackBar或切换到Login页面!

当我调试代码时,我发现它实际上将状态更改为(VerificationEmailSentState),然后立即将其更改回InitialState,因此BlocBuilder中的代码没有被执行,因为当我更改时它被中断(重建) state to InitialState。为了确保,我在第一次改变状态后延迟1秒并且它工作(SnackBar出现)。

问题是为什么会发生这种情况?并推迟国家的第二次改变是一个好主意?如果不是,没有它如何让它工作?

//SignupBloc
await user.sendEmailVerification();
yield SignupVerificationEmailSentState();
await Future.delayed(Duration(seconds: 1)); //Will not work without it.
yield SignupInitialState();
//LoginSignupPage
BlocBuilder<SignupEvent, SignupState>(
      bloc: _signupBloc,
      builder: (BuildContext context, SignupState state) {
        if (state is SignupVerificationEmailSentState) {
          print("About to show SnackBar");//Printed only with delay
          raiseSnackBar();
          swtichToLogin();
        }
        return ...
      }
)
flutter yield bloc
1个回答
1
投票

这实际上是你要求它做的行为。你正在屈服于一个州(SignupVerificationEmailSentState),然后立即将其改回另一个州SignupInitialState

你在状态raiseSnackBar()时调用is SignupVerificationEmailSentState,这是正确的,但是,正如你所指出的那样,视图正在重建,因为你实际上是在没有足够时间让用户看到SnackBar的情况下还原它。 await Future.delayed(Duration(seconds: 1))实际上给了它第二次展示它。

这不是一个“坏方法”,它将取决于您的应用程序的流程以及您实际尝试实现的目标。但是,我宁愿这样做

Future.delayed(Duration(seconds: 1)).then((_) => yield SignupInitialState());

假设你可能有一些指令,它不会阻止任何其他指令在该方法调用中的那个之后运行。如果你不这样做,那没关系。

如果你想确保在SnackBar显示1秒后它只恢复到初始状态,请删除以下两行:

await Future.delayed(Duration(seconds: 1)); //Will not work without it.
yield SignupInitialState();

你可以用这样的东西做到这一点:

  Scaffold.of(context)
            .showSnackBar(
              SnackBar(
                content: Text('Something...'),
                duration: Duration(seconds: 1),
              ),
            )
            .closed
            .then((_) => bloc.revertToSignupInitialState());
© www.soinside.com 2019 - 2024. All rights reserved.