由于 mapEventToState 导致的 Flutter bloc 迁移不起作用

我正在关注 migration 到新的 bloc 8.0.0。我正在尝试删除 **mapEventToState** 但我很难这样做。你能帮我怎么做。我在下面尝试过,但它不起作用。

旧代码:

class SignInBloc extends Bloc<SignInEvent, SignInState> {
  final AuthenticationRepository authenticationRepository;
  final UserDataRepository userDataRepository;

  SignInBloc(
      {required this.authenticationRepository,
      required this.userDataRepository})
      : super(SignInInitialState());

  SignInState get initialState => SignInInitialState();

  @override
  Stream<SignInState> mapEventToState(
    SignInEvent event,
  ) async* {
    if (event is SignInWithGoogle) {
      yield* mapSignInWithGoogleToState();
    }
  }

Stream<SignInState> mapSignInWithGoogleToState() async* {
    yield SignInWithGoogleInProgressState();
    try {
      String res = await authenticationRepository.signInWithGoogle();
      yield SignInWithGoogleCompletedState(res);
    } catch (e) {
      print(e);
      yield SignInWithGoogleFailedState();
    }
  }
...

迁移代码(不起作用):

class SignInBloc extends Bloc<SignInEvent, SignInState> {
  final AuthenticationRepository authenticationRepository;
  final UserDataRepository userDataRepository;

  SignInBloc(
      {required this.authenticationRepository,
        required this.userDataRepository})
      : super(SignInInitialState())
  {
    SignInState get initialState => SignInInitialState();

    on<SignInWithGoogle>((event, emit) => emit(mapSignInWithGoogleToState()));
  }

Stream<SignInState> mapSignInWithGoogleToState() async* {
    yield SignInWithGoogleInProgressState();
    try {
      String res = await authenticationRepository.signInWithGoogle();
      yield SignInWithGoogleCompletedState(res);
    } catch (e) {
      print(e);
      yield SignInWithGoogleFailedState();
    }
  }
...
stack overflow Flutter bloc migration due to mapEventToState is not working
原文答案
author avatar

接受的答案

您的问题是 mapSignInWithGoogleToState() 返回状态的 Stream ,但是每次需要发出新状态时,新结构都需要显式调用 emit

class SignInBloc extends Bloc<SignInEvent, SignInState> {
  final AuthenticationRepository authenticationRepository;
  final UserDataRepository userDataRepository;

  SignInBloc({required this.authenticationRepository,
    required this.userDataRepository})
      : super(SignInInitialState()) {
    on<SignInWithGoogle>(mapSignInWithGoogleToState);
  }

  Future<void> mapSignInWithGoogleToState(
      SignInWithGoogle event,
      Emitter<SignInState> emit,
  ) async {
    emit(SignInWithGoogleInProgressState());
    try {
      String res = await authenticationRepository.signInWithGoogle();
      emit(SignInWithGoogleCompletedState(res));
    } catch (e) {
      print(e);
      emit(SignInWithGoogleFailedState());
    }
  }
}

以下是关于“为什么?”的更多信息: https://bloclibrary.dev/#/migration?id=rationale-7


答案:

作者头像

getter 不属于构造函数主体,我想它不再需要了。你可以这样解决问题:

class SignInBloc extends Bloc<SignInEvent, SignInState> {
  final AuthenticationRepository authenticationRepository;
  final UserDataRepository userDataRepository;

  SignInBloc({required this.authenticationRepository,
    required this.userDataRepository})
      : super(SignInInitialState()) {
    on<SignInWithGoogle>(_handleSignInWithGoogleEvent);
  }

  Future<void> _handleSignInWithGoogleEvent(
      SignInWithGoogle event,
      Emitter<SignInState> emit,
  ) async {
    // TODO do your thing and create and emit the SignInWithGoogleState
    emit(SignInWithGoogleState());
  }
}

请注意,bloc v8 中的事件不再按顺序处理,而是同时处理。阅读这篇博文: https://verygood.ventures/blog/how-to-use-bloc-with-streams-and-concurrency