Flutter Application Bloc 侦听器未接收状态更新

Nie*_*ijk 9 dart flutter bloc flutter-bloc

我使用 flutter Bloc 将用户导航到登录页面或主屏幕,具体取决于用户是否经过身份验证。但是,在初始状态更改后,当我更改身份验证状态时,侦听器不会触发。

听众:

Widget build(BuildContext context) {
  return BlocListener<AuthenticationBloc, AuthenticationState>(
    listener: (context, state) {
      // Listener never gets called on statechange after the initial app startup

      // navigation based on authentication 
      }
    },
    child: SplashPage(),
  );
}
Run Code Online (Sandbox Code Playgroud)

提供者在父小部件中初始化:

AuthenticationRepository authRepo = AuthenticationRepository();

Widget build(BuildContext context) {
  return MultiBlocProvider(
    providers: [
      BlocProvider<AuthenticationBloc>(
        create: (BuildContext context) =>
            AuthenticationBloc(authenticationRepository: authRepo),
      ),
      /*
         Other Providers
      */
    ],
    child: MaterialApp(
      title: 'myApp',
      home: StartUpPage(),
    ),
  );
Run Code Online (Sandbox Code Playgroud)

当用户登录时,mapEventState 在 AuthenticationBloc 中被调用:

class AuthenticationBloc
    extends Bloc<AuthenticationEvent, AuthenticationState> {
  AuthenticationBloc({
    @required AuthenticationRepository authenticationRepository,
  })  : assert(authenticationRepository != null),
        _authenticationRepository = authenticationRepository,
        super(const AuthenticationState.unknown()) {
    _userSubscription = _authenticationRepository.userStream.listen(
      (user) => add(AuthenticationUserChanged(user)),
    );
  }

  final AuthenticationRepository _authenticationRepository;
  StreamSubscription<User> _userSubscription;

  @override
  Stream<AuthenticationState> mapEventToState(
    AuthenticationEvent event,
  ) async* {
    if (event is AuthenticationUserChanged) {
      yield _mapAuthenticationUserChangedToState(event);
    } else if (event is AuthenticationLogoutRequested) {
      unawaited(_authenticationRepository.logOut());
    }
  }

  @override
  Future<void> close() {
    _userSubscription?.cancel();
    return super.close();
  }

  AuthenticationState _mapAuthenticationUserChangedToState(
    AuthenticationUserChanged event,
  ) =>
      event.user != User.empty
          ? AuthenticationState.authenticated(event.user)
          : const AuthenticationState.unauthenticated();
}
Run Code Online (Sandbox Code Playgroud)

我希望当用户登录并且 AuthenticationState 更改时触发侦听器。如果有人知道我做错了什么或者我错过了什么,我很想听听。

2021 年 2 月 8 日编辑:

我再次检查了使用简单按钮登录后状态是否发生变化。这样,我可以确认状态确实发生了变化并保存了正确的用户数据和身份验证状态。我确认的另一件事是,当用户登录时,使用 BlocBuilder<AuthenticationBloc, AuthenticationState> 的 BlocBuilder会正确更新。

2021 年 10 月 2 日编辑:

整个认证状态:

enum AuthenticationStatus { authenticated, unauthenticated, unknown }

class AuthenticationState extends Equatable {
  const AuthenticationState._({
    this.status = AuthenticationStatus.unknown,
    this.user = User.empty,
  });

  const AuthenticationState.unknown() : this._();

  const AuthenticationState.authenticated(User user)
      : this._(status: AuthenticationStatus.authenticated, user: user);

  const AuthenticationState.unauthenticated()
      : this._(status: AuthenticationStatus.unauthenticated, user: User.empty);

  final AuthenticationStatus status;
  final User user;

  @override
  List<Object> get props => [status, user];
}
Run Code Online (Sandbox Code Playgroud)

2021 年 2 月 12 日编辑:

删除了不相关的代码

2021 年 2 月 15 日编辑:

添加了整个身份验证块

Nic*_*her 3

你能列出你的整个小部件树吗?

我想知道您的第一个小部件(包含侦听器的小部件)实际上是否没有被渲染(比如说,因为您在树中的某处有一个 if/else ,这意味着它在事件触发时实际上并未显示) 。

您可以使用 Flutter 检查器进行检查。否则,它是否在同一个 BuildContext 中运行?

如果您显示整个小部件树,这将更容易诊断。