更新身份验证状态时未调用 Bloc 侦听器?

Posted

技术标签:

【中文标题】更新身份验证状态时未调用 Bloc 侦听器?【英文标题】:Bloc listener not called when authentication state is updated? 【发布时间】:2021-04-26 21:45:00 【问题描述】:

任何帮助将不胜感激,我不知道问题出在哪里。我有一个基于 AuthCheckState 的启动页面,如果用户已注册,他会被推送到主屏幕或注册/欢迎屏幕。

在注册页面内,如果我成功注册 Firebase,我的 SignInForm 侦听器会被触发,用户会被推回 SplashScreen,并且新的 authCheckEvent 会发送到我的 AuthCheck 块。

然后我的 AuthCheck 块产生更新的状态(经过身份验证),但不调用 SplashPage 内的侦听器。

class SplashPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return BlocListener<AuthCheckBloc, AuthCheckState>(
      listener: (context, state) 
        state.map(
          initial: (_) 
            print("Inital STate");
          ,
          authenticated: (_) 
            print("Authenticated STate");
            Navigator.of(context).pushReplacement(
              MaterialPageRoute(
                builder: (context) => HomePage(),
              ),
            );
          ,
          unauthenticated: (_) 
            print("Unathenticated state STate");
            Navigator.of(context).pushReplacement(
              MaterialPageRoute(
                builder: (context) => WelcomePage(),
              ),
            );
          ,
        );
      ,
      child: SafeArea(
        child: Scaffold(
          body: Center(
            child: Column(
              children: [
                Spacer(),
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20.0),
                  child: Image.asset(
                    "assets/logo.PNG",
                    width: MediaQuery.of(context).size.width * 0.5,
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20.0),
                  child: CircularProgressIndicator(),
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20.0),
                  child: const Text("Loading..."),
                ),
                Spacer(),
              ],
            ),
          ),
        ),
      ),
    );
  


class SignUpPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return SafeArea(
      child: Scaffold(
        body: BlocConsumer<SignInFormBloc, SignInFormState>(
          listener: (context, state) 
            if (state.errorMessage.isNotEmpty) 
              Scaffold.of(context).showSnackBar(
                SnackBar(
                  content: Text(state.errorMessage),
                  duration: Duration(seconds: 1),
                ),
              );
            
            if (state.isAuthStateChanged) 
              Navigator.of(context).pushReplacement(
                MaterialPageRoute(
                  builder: (context) => SplashPage(),
                ),
              );
              //Add email verification? Show snackbar, asking to verify email, so that they can log in?
              //Send back to WelcomeScreen, or send back to a temp screen where it waits for email verification?
              context.read<AuthCheckBloc>().add(
                    const AuthCheckEvent.authCheckRequested(),
                  );
            
          ,
builder: //Sign Form UI here...
class AuthCheckBloc extends Bloc<AuthCheckEvent, AuthCheckState> 
  final AuthRepository _authRepository;

  AuthCheckBloc(this._authRepository) : super(const AuthCheckState.initial());

  @override
  Stream<AuthCheckState> mapEventToState(
    AuthCheckEvent event,
  ) async* 
    yield* event.map(
      authCheckRequested: (e) async* 
        print("auth check CALLLED");
        final bool = _authRepository.isUserSignedIn();
        if (bool) 
          yield const AuthCheckState.authenticated();
          print("yielded authenticated");
         else 
          yield const AuthCheckState.unauthenticated();
        
      ,
      signOutPressed: (e) async* 
        String returnValue = await _authRepository.signOut();
        if (returnValue == kSuccess) 
          yield const AuthCheckState.unauthenticated();
         else 
          print("There was an error signing out!");
        
      ,
    );
  

【问题讨论】:

【参考方案1】:

更新:没有找到问题所在,所以我改变了我的解决方案,但不得不为此做出一些牺牲。

我将 SplashPage 转换为 Stateful 小部件,从 SignUpPage 中删除事件并将事件 authCheckRequested 放入 SplashPage init() 方法中,因此每次初始化 SplashPage 时,它​​都会执行检查并推送到相应的屏幕。

【讨论】:

以上是关于更新身份验证状态时未调用 Bloc 侦听器?的主要内容,如果未能解决你的问题,请参考以下文章

在块中调用时未发出 CLLocationManager 身份验证请求

Flutter Bloc 状态更改未使用 get_it 更新 UI

使用 Flutter BLoC 模式跟踪多个状态

使用 BLoC 进行 Flutter Firebase 电话身份验证

Flutter bloc 和 Firebase 电话身份验证

如何将 Flutter Bloc 与 Firebase 电话身份验证一起使用