【问题标题】:Check authentication state using stream not working in Flutter使用流在 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();
              })
        ],
      ),
    );
  }
}

【问题讨论】:

    标签: firebase flutter firebase-authentication google-signin


    【解决方案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 方法是撤销身份验证/注销用户的方法。

    【讨论】:

      猜你喜欢
      • 2020-12-19
      • 2018-09-23
      • 1970-01-01
      • 2020-02-09
      • 1970-01-01
      • 1970-01-01
      • 2017-12-09
      • 2019-12-20
      • 2011-08-06
      相关资源
      最近更新 更多