【问题标题】:Return a stream from a function从函数返回流
【发布时间】:2021-01-23 16:49:07
【问题描述】:

我正在使用 Riverpod 进行状态管理。

class SignInStateNotifier extends StateNotifier<SignInFormStates> {
  SignInStateNotifier(this._authFacade) : super(SignInFormStates.initial());

  final IAuthFacade _authFacade;

  void mapEventToState(SignInFormEvents signInFormEvents) {
    state = signInFormEvents.when(
        emailChanged: (value) => state.copyWith(
              emailAddress: EmailAddress(value),
              authFailureOrSuccess: none(),
            ),
        passwordChanged: (value) => state.copyWith(
              password: Password(value),
              authFailureOrSuccess: none(),
            ),
        signInWithEmailAndPasswordPressed: () async* {
          yield* _performActionOnAuthFacade(
              _authFacade.signInWithEmailAndPassword);
        });
  }

我在这里遇到错误

signInWithEmailAndPasswordPressed: () async* {
              yield* _performActionOnAuthFacade(
                  _authFacade.signInWithEmailAndPassword);
            });

参数类型'Stream Function()'不能是 分配给参数类型“SignInFormStates Function()”。

我的__performActionOnAuthFacade 函数

Stream<SignInFormStates> _performActionOnAuthFacade(
    Future<Either<AuthFailure, Unit>> Function({
      @required EmailAddress emailAddress,
      @required Password password,
    })
        forwardCall,
  ) async* {
    Either<AuthFailure, Unit> failureOrSuccess;
    if (state.emailAddress.isValid() && state.password.isValid()) {
      yield state.copyWith(
        isSubmitting: true,
        authFailureOrSuccess: none(),
      );
      failureOrSuccess = await _authFacade.registerWithEmailAndPassword(
          emailAddress: state.emailAddress, password: state.password);
    }
    yield state.copyWith(
        isSubmitting: false,
        showErrorMessage: true,
        authFailureOrSuccess: optionOf(failureOrSuccess));
  }

请给出解决此错误的解决方案。提前致谢。

【问题讨论】:

    标签: flutter dart flutter-layout state-management riverpod


    【解决方案1】:

    如果您想使用StateNotifier 来执行此操作,而无需使用Stream 来更改状态,您需要执行以下操作:

    class SignInFormStateNotifier extends StateNotifier<SignInFormState> {
      final IAuthFacade _authFacade;
    
      SignInFormStateNotifier(this._authFacade) : super(SignInFormState.initial());
    
      Future handleEvent(SignInFormEvent event) async {
        event.map(
          // email changed
          emailChanged: (event) {
            state = state.copyWith(
              emailAddress: EmailAddress(event.email),
              authFailureOrSuccessOption: none(),
            );
          },
          // password changed
          passwordChanged: (event) {
            state = state.copyWith(
              password: Password(event.password),
              authFailureOrSuccessOption: none(),
            );
          },
          // register with email and password
          registerWithEmailAndPassword: (event) async {
            await _performActionWithEmailAndPassword(
              _authFacade.registerWithEmailAndPassword,
            );
          },
          // sign in with email and password
          signInWithEmailAndPassword: (event) async {
            await _performActionWithEmailAndPassword(
              _authFacade.signInWithEmailAndPassword,
            );
          },
          // sign in with Google
          signInWithGoogle: (event) async {
            state = state.copyWith(
              isSubmitting: true,
              authFailureOrSuccessOption: none(),
            );
            final result = await _authFacade.signInWithGoogle();
    
            state = state.copyWith(
              isSubmitting: false,
              authFailureOrSuccessOption: some(result),
            );
          },
        );
      }
    
      Future _performActionWithEmailAndPassword(
        Future<Either<AuthFailure, Unit>> Function({
          @required EmailAddress emailAddress,
          @required Password password,
        })
            action,
      ) async {
        Either<AuthFailure, Unit> result;
        final isEmailValid = state.emailAddress.isValid();
        final isPasswordValid = state.password.isValid();
    
        if (isEmailValid && isPasswordValid) {
          state = state.copyWith(
            isSubmitting: true,
            authFailureOrSuccessOption: none(),
          );
    
          result = await action(
            emailAddress: state.emailAddress,
            password: state.password,
          );
    
          state = state.copyWith(
            authFailureOrSuccessOption: some(result),
          );
        }
        state = state.copyWith(
          isSubmitting: false,
          showErrorMessages: true,
          authFailureOrSuccessOption: optionOf(result),
        );
      }
    }
    

    【讨论】:

    • 这行得通!非常感谢,@Viacheslav。但是您能解释一下为什么这样有效吗?我们不想使用流并改用 Future 的原因是什么?
    • @PythonHub,它可以工作,因为你使用的是StateNotifier和Riverpod的StateNotifierProvider,我没有太多时间解释,因为我的英语不好。但我推荐你观看 Reso Coder 的视频《Flutter StateNotifier + Riverpod 教程》link。当您调用state = SomeState(...) 时,正在从watch 方法监听此StateNotifierProviderConsumer 触发重建小部件树。
    • 非常感谢,我会看教程
    【解决方案2】:

    我不知道您的 SignInFormStates 类,但它不希望在 signInWithEmailAndPasswordPressed 中调用 Stream 函数,但可能是一个空的 voidCallback?

    state = signInFormEvents.when(
            emailChanged: (value) => state.copyWith(
                  emailAddress: EmailAddress(value),
                  authFailureOrSuccess: none(),
                ),
            passwordChanged: (value) => state.copyWith(
                  password: Password(value),
                  authFailureOrSuccess: none(),
                ),
            signInWithEmailAndPasswordPressed: () => () async* {  //so a SignInFormStates Function() calls your stream function
              yield* _performActionOnAuthFacade(
                  _authFacade.signInWithEmailAndPassword);
            });
    

    但仍然有机会在这之后它会给你一些其他错误,告诉你 state is expected to be type SignInFormStates 并且你传递给它一个流函数,或者它实际上可能等待流完成并返回产生了新的状态,唯一要做的就是尝试看看会发生什么

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-09
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 2013-05-15
      相关资源
      最近更新 更多