【问题标题】:Flutter bloc migration due to mapEventToState is not working由于 mapEventToState 导致的 Flutter bloc 迁移不起作用
【发布时间】:2022-01-01 14:15:13
【问题描述】:

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

旧代码:

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();
    }
  }
...

【问题讨论】:

  • 对我来说看起来是正确的。它到底是怎么工作的?也许还为mapSignInWithGoogleToState添加一些代码
  • 我已经添加了

标签: flutter bloc


【解决方案1】:

您的问题是 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-6

【讨论】:

    【解决方案2】:

    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

    【讨论】:

    • 您好,感谢您的评论。我还更新了上面显示 mapSignInWithGoogleToState() 的代码。我也会看看你提供的链接。
    猜你喜欢
    • 2022-07-10
    • 2021-12-05
    • 2020-07-05
    • 2021-11-22
    • 1970-01-01
    • 2021-04-21
    • 2020-07-21
    • 2021-05-20
    • 1970-01-01
    相关资源
    最近更新 更多