使用流在 Flutter 中不起作用检查身份验证状态

Posted

技术标签:

【中文标题】使用流在 Flutter 中不起作用检查身份验证状态【英文标题】:Check authentication state using stream not working in Flutter 【发布时间】:2021-07-12 15:43:11 【问题描述】:

我正在使用GoogleSignIn

在我的初始屏幕上,我使用StreamBuilder 检查用户是否已登录,并根据该数据尝试显示登录屏幕或主屏幕。

当我卸载并重新安装应用程序时,它首次显示登录屏幕。然后,即使我从应用程序中注销,它也总是显示主屏幕。

下面是我的Splash Screen代码:

class SplashScreen extends StatefulWidget 
  @override
  _SplashScreenState createState() => _SplashScreenState();


class _SplashScreenState extends State<SplashScreen> 
  @override
  Widget build(BuildContext context) 
    SizeConfig().init(context);
    return StreamBuilder(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (BuildContext context, AsyncSnapshot<User> snapshot) 
        if (snapshot.hasData) 
          print(snapshot.hasData);
          return AnimatedSplashScreen(
            splashIconSize: SizeConfig.blockSizeVertical * 16,
            splashTransition: SplashTransition.fadeTransition,
            nextScreen: HomeScreen(),
            splash: kLogoImage,
            duration: 800,
          );
         else 
          print(snapshot.hasData);
          return AnimatedSplashScreen(
            splashIconSize: SizeConfig.blockSizeVertical * 16,
            splashTransition: SplashTransition.fadeTransition,
            nextScreen: LoginScreen(),
            splash: kLogoImage,
            duration: 800,
          );
        
      ,
    );
  

下面是我的Home Screen代码:

class HomeScreen extends StatefulWidget 
  @override
  _HomeScreenState createState() => _HomeScreenState();


class _HomeScreenState extends State<HomeScreen> 
  final GoogleSignIn googleSignIn = GoogleSignIn();
  User firebaseUser;

  signOut() async 
    await googleSignIn.signOut();
    Navigator.pushReplacementNamed(context, MyRoutes.loginScreen);
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(
            child: Text('Hello'),
          ),
          MaterialButton(
              child: Text('Log out'),
              color: Colors.red,
              onPressed: () 
                signOut();
              )
        ],
      ),
    );
  

【问题讨论】:

【参考方案1】:

会不会是 GoogleSignIn 和 Firebase 不一样?

尝试在您的home screen 上将googleSignIn.signOut() 替换为FirebaseAuth.instance.signOut()

【讨论】:

我很高兴您的问题得到了解决,但您为什么同时使用 google_sign_infirebase_auth 我不知道googleSignIn.signOut() 有什么问题,但是用FirebaseAuth.instance.signOut() 替换它可以解决问题。可能是因为googleSignIn.signOut() 没有更新authStateChanges() 流。但是在 FirebaseAuth.instance.signOut() 方法的文档中说 FirebaseAuth 的 signOut 方法更新了 authStateChanges() 流。这可能是失败的原因。 我想在我的应用程序中使用GoogleSignIn。但我还需要其他数据,例如currentUserprofilePhoto 等等。这可以使用 FirebaseAuth 来实现。所以我正在使用它。 You can。如果您想让您的用户仅使用他们的 Google 帐户登录,请使用 google_sign_in 并去掉 firebase_auth。如果您想提供“使用 google 登录”以及更多登录选项(使用 Apple 登录、使用 facebook 登录、传统电子邮件/密码等),请使用 firebase_auth 并摆脱 google_sign_in。跨度> 仅供参考:如果您计划在 ios 应用商店上发布应用并实施“使用谷歌登录”,则还必须以per Apple's rules 的身份使用苹果登录。【参考方案2】:

我不知道为什么它不起作用,我认为您的代码是正确的,但我有另一种方法可以使用流提供程序而不是流生成器

将流提供程序包装在您的材料应用程序或 cupirtinoapp 之上:

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return StreamProvider.value(
      value: firebaseauht.inistance.onauthchange,
      child: MaterialApp(
        home: Wholescreen(),
      ),
    );
  

然后全屏调用提供者:

class Wholescreen extends StatelessWidget 

  @override
  Widget build(BuildContext context) 
    var provider = Provider.of<User>(context);
    if (provider!=null) 
      return AnimatedSplashScreen(
            splashIconSize: SizeConfig.blockSizeVertical * 16,
            splashTransition: SplashTransition.fadeTransition,
            nextScreen: HomeScreen(),
            splash: kLogoImage,
            duration: 800,
     else 
      return AnimatedSplashScreen(
            splashIconSize: SizeConfig.blockSizeVertical * 16,
            splashTransition: SplashTransition.fadeTransition,
            nextScreen: LoginScreen(),
            splash: kLogoImage,
            duration: 800,
          ); 
    
  

【讨论】:

它要求我提供initialData。我应该放什么?【参考方案3】:

改变这个:

  signOut() async 
    await googleSignIn.signOut();
    Navigator.pushReplacementNamed(context, MyRoutes.loginScreen);
  

进入这个:

  signOut() async 
    await googleSignIn.disconnect();
    Navigator.pushReplacementNamed(context, MyRoutes.loginScreen);
  

根据文档,disconnect 方法是撤销身份验证/注销用户的方法。

【讨论】:

以上是关于使用流在 Flutter 中不起作用检查身份验证状态的主要内容,如果未能解决你的问题,请参考以下文章

身份验证在 FirebaseStorage Flutter 中不起作用

Spring Security Filter 测试,身份验证在 POSTMAN 中不起作用

使用 Flutter 的 Firebase 身份验证不起作用

firebase电话身份验证在发行版中不起作用[重复]

Flex 流在 IE11 中不起作用

Cookie 持久性在 OWIN 身份验证中不起作用