#flutter #flutter-bloc
#трепетать #флаттер-блок
Вопрос:
Итак, я работал с Django rest framework, создавая свои API и все такое. И я хотел проверить, смогу ли я получить ответ от бэкенда. Итак, я смог получить ответ. Но я видел некоторые проблемы на консоли отладки. Пожалуйста, помогите мне разобраться в проблеме. Это то, что я получил на консоли отладки.
Restarted application in 1,314ms. I/flutter ( 1751): {"token":"0d15f2d45f11869174395d623c066080bd2ade52"} E/flutter ( 1751): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: 'package:bloc/src/bloc.dart': Failed assertion: line 232 pos 7: '!_isCompleted': E/flutter ( 1751): E/flutter ( 1751): E/flutter ( 1751): emit was called after an event handler completed normally. E/flutter ( 1751): This is usually due to an unawaited future in an event handler. E/flutter ( 1751): Please make sure to await all asynchronous operations with event handlers E/flutter ( 1751): and use emit.isDone after asynchronous operations before calling emit() to E/flutter ( 1751): ensure the event handler has not completed. E/flutter ( 1751): E/flutter ( 1751): **BAD** E/flutter ( 1751): onlt;Eventgt;((event, emit) { E/flutter ( 1751): future.whenComplete(() =gt; emit(...)); E/flutter ( 1751): }); E/flutter ( 1751): E/flutter ( 1751): **GOOD** E/flutter ( 1751): onlt;Eventgt;((event, emit) async { E/flutter ( 1751): await future.whenComplete(() =gt; emit(...)); E/flutter ( 1751): }); E/flutter ( 1751): E/flutter ( 1751): #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39) E/flutter ( 1751): #1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5) E/flutter ( 1751): #2 _Emitter.call E/flutter ( 1751): #3 new LoginFormBloc.lt;anonymous closuregt;.lt;anonymous closuregt; E/flutter ( 1751): lt;asynchronous suspensiongt; E/flutter ( 1751): Reloaded 1 of 746 libraries in 1,055ms.
Вот мой исходный код:
login_form_event.dart
part of 'login_form_bloc.dart'; @freezed class LoginFormEvent with _$LoginFormEvent { const factory LoginFormEvent.emailChanged(String emailStr) = _EmailChanged; const factory LoginFormEvent.passwordChanged(String passwordStr) = _PasswordChanged; const factory LoginFormEvent.loggedIn() = _LoggedIn; }
login_form_state.dart
part of 'login_form_bloc.dart'; @freezed class LoginFormState with _$LoginFormState { const factory LoginFormState({ required EmailAddress emailAddress, required Password password, required bool isSubmitting, required bool showErrorMessages, required Optionlt;Eitherlt;AuthFailure, TokenValuegt;gt; authFailureOrSuccessOption, }) = _LoginFormState; factory LoginFormState.initial() =gt; LoginFormState( emailAddress: EmailAddress(''), password: Password(''), isSubmitting: false, showErrorMessages: false, authFailureOrSuccessOption: none(), ); }
login_form_bloc.dart
class LoginFormBloc extends Bloclt;LoginFormEvent, LoginFormStategt; { LoginFormBloc(this._getAuthInfo) : super(LoginFormState.initial()) { onlt;LoginFormEventgt;( (event, emit) { event.map( emailChanged: (e) { emit( state.copyWith( emailAddress: EmailAddress(e.emailStr), authFailureOrSuccessOption: none(), ), ); }, passwordChanged: (e) { emit( state.copyWith( password: Password(e.passwordStr), authFailureOrSuccessOption: none(), ), ); }, loggedIn: (e) async { final isEmailValid = state.emailAddress.value.isRight(); final isPasswordValid = state.password.value.isRight(); Eitherlt;AuthFailure, TokenValuegt;? loginFailureOrSuccess; if (isEmailValid amp;amp; isPasswordValid) { emit( state.copyWith( isSubmitting: true, authFailureOrSuccessOption: none(), ), ); loginFailureOrSuccess = await _getAuthInfo( Params( emailAddress: state.emailAddress, password: state.password, ), ); } //The error is pointed to this emit below emit( state.copyWith( isSubmitting: false, showErrorMessages: true, authFailureOrSuccessOption: optionOf(loginFailureOrSuccess), ), ); }, ); }, ); } final GetAuthToken _getAuthInfo; }
Ошибка указана на 2-м выделении внутри обработчика событий LoggedIn.
Комментарии:
1. Что случилось с методом карты? Почему бы не использовать обычную
onlt;Eventgt;
нотацию, это, вероятно, исправит проблему… Если вы не хотите использовать обычныйon
метод, не могли бы вы показать реализацию этогоmap
метода?2. Метод карты существует, потому что я использовал объединения, предлагаемые замороженным пакетом.
3. @h8moss смотрите обновленный пост. Может быть, это поможет.
4. Сейчас этот вопрос решен.
5. Я вижу, рад слышать, что проблема устранена
Ответ №1:
Все, что мне нужно было сделать, это добавить await
ключевое слово перед вызовом event.map и пометить функцию, async
как показано ниже. Кроме того, я прямо упомянул, что должны возвращать мои отдельные обработчики событий. В данном случае так оно и было FutureOrlt;voidgt;
.
class LoginFormBloc extends Bloclt;LoginFormEvent, LoginFormStategt; { LoginFormBloc(this._getAuthInfo) : super(LoginFormState.initial()) { onlt;LoginFormEventgt;( (event, emit) async { await event.maplt;FutureOrlt;voidgt;gt;( emailChanged: (e) { emit( state.copyWith( emailAddress: EmailAddress(e.emailStr), authFailureOrSuccessOption: none(), ), ); }, passwordChanged: (e) { emit( state.copyWith( password: Password(e.passwordStr), authFailureOrSuccessOption: none(), ), ); }, loggedIn: (e) async { final isEmailValid = state.emailAddress.value.isRight(); final isPasswordValid = state.password.value.isRight(); Eitherlt;AuthFailure, TokenValuegt;? loginFailureOrSuccess; if (isEmailValid amp;amp; isPasswordValid) { emit( state.copyWith( isSubmitting: true, authFailureOrSuccessOption: none(), ), ); loginFailureOrSuccess = await _getAuthInfo( Params( emailAddress: state.emailAddress, password: state.password, ), ); } emit( state.copyWith( isSubmitting: false, showErrorMessages: true, authFailureOrSuccessOption: optionOf(loginFailureOrSuccess), ), ); }, ); }, ); } final GetAuthToken _getAuthInfo; }