Почему состояние bloc не обновляется?

Как лучше всего организовать вход в аккаунт для приложения, используя два блока: один для определения глобального состояния Auth, а второй для авторизации?
  • 6 февраля 2024 г. 15:18
Ответы на вопрос 1
Если состояние в BLoC (Business Logic Component) не обновляется, то причин может быть несколько. Вот некоторые из них:

1. В методе, который должен обновлять состояние, не вызывается `emit()`.
2. Может быть ошибка в логике или условиях, при которых должно произойти обновление состояния.
3. Потоки данных могут быть неправильно настроены, и слушатели не получают изменения состояния.
4. Виджет, использующий BLoC, может быть неправильно построен и не реагирует на изменения состояния из-за неправильного использования `BlocBuilder`, `BlocListener` или `BlocConsumer`.
5. Возможно, забыли добавить `BlocProvider` в верхнюю часть дерева виджетов или неправильно используют контекст для доступа к BLoC.
6. Если используете `equatable`, убедитесь, что определены все свойства, которые должны вызывать обновление, в списке props.

Чтобы организовать авторизацию в приложении с использованием двух BLoC'ов, можно использовать следующую стратегию:

### AuthBloc:
Этот BLoC будет отвечать за глобальное состояние авторизации пользователя. Он будет содержать состояния, такие как Unauthenticated, Authenticated и Loading.

Пример AuthBloc:

```dart
enum AuthStatus {
  unauthenticated,
  authenticated,
  loading,
}

class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final UserRepository userRepository;
  
  AuthBloc({required this.userRepository}) : super(Unauthenticated()) {
    on<AppStarted>(_onAppStarted);
    on<LoggedIn>(_onLoggedIn);
    on<LoggedOut>(_onLoggedOut);
  }
  
  void _onAppStarted(AppStarted event, Emitter<AuthState> emit) {
    final bool hasToken = await userRepository.hasToken();
    if (hasToken) {
      emit(Authenticated());
    } else {
      emit(Unauthenticated());
    }
  }
  
  void _onLoggedIn(LoggedIn event, Emitter<AuthState> emit) {
    emit(Authenticated());
  }
  
  void _onLoggedOut(LoggedOut event, Emitter<AuthState> emit) {
    await userRepository.deleteToken();
    emit(Unauthenticated());
  }
}
```

### LoginBloc:
Этот BLoC будет отвечать за процесс входа в аккаунт, включая валидацию формы авторизации и передачу данных для авторизации в `UserRepository`.

Пример LoginBloc:

```dart
class LoginBloc extends Bloc<LoginEvent, LoginState> {
  final AuthBloc authBloc;
  final UserRepository userRepository;

  LoginBloc({
    required this.authBloc,
    required this.userRepository,
  }) : super(LoginInitial()) {
    on<LoginButtonPressed>(_onLoginButtonPressed);
  }
  
  void _onLoginButtonPressed(LoginButtonPressed event, Emitter<LoginState> emit) async {
    emit(LoginLoading());
    try {
      final token = await userRepository.authenticate(
        username: event.username,
        password: event.password,
      );
      authBloc.add(LoggedIn(token: token));
      emit(LoginInitial());
    } catch (error) {
      emit(LoginFailure(error: error.toString()));
    }
  }
}
```

### Реализация пользовательского интерфейса:
1. Используйте `BlocProvider` для предоставления `AuthBloc` в вашем приложении.
2. В виджете уровня приложения используйте `BlocListener` для прослушивания изменений состояния в `AuthBloc`.
3. Используйте `BlocProvider` для предоставления `LoginBloc` на экране входа.
4. Используйте `BlocBuilder` для управления состоянием кнопки входа и отображения сообщений об ошибке на экране входа.

Это обеспечит чистое разделение ответственности и легко масштабируемую ар
Похожие вопросы