Return 来自函数的流

Return a stream from a function

我正在使用 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);
            });

The argument type 'Stream Function()' can't be assigned to the parameter type '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));
  }

请给出解决这个错误的方法。提前致谢。

我不知道你的 SignInFormStates class 但它不希望在 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);
        });

但是在那之后它仍然有可能给你一些其他错误告诉你状态期望是 SignInFormStates 类型并且你传递给它一个流函数,或者它实际上等待流到完成并 return 新状态产生,唯一要做的就是尝试看看会发生什么

如果你想用 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),
    );
  }
}