首页 > 解决方案 > 如何确定用户在使用 Flutter 启动应用程序时是否仍登录 FireBase?

问题描述

当应用程序启动时,我想检查用户是否已登录,并基于此我想显示login/signup页面或homepage. 从文档中,我知道一旦用户登录,他或她的会话就会持续存在,并且每次都要求用户登录是没有意义的

适用于所有平台的 Firebase SDK 提供开箱即用的支持,以确保您的用户的身份验证状态在应用重新启动或页面重新加载时保持不变。

在 Android 和 iOS 等原生平台上,此行为是不可配置的,并且用户的身份验证状态将在应用重新启动之间保留在设备上。用户可以通过设备设置清除应用程序缓存的数据,这将擦除存储的任何现有状态。

我正在尝试使用以下代码尝试实现上述目标:

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // to check if we're already logged in or not
  User? user = FirebaseAuth.instance.currentUser;

  @override
  void initState() {
    print(user);
    print(user!.email);
    if (user != null){
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('${user!.email} signed in'),
        ),
      );
      Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => HomeScreen()),
      );
    }
    super.initState();
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Icon(Icons.verified_user, size: 98,),
            SizedBox(height: 5,),
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SignInScreen()),
                );
              },
              child: Text('LOGIN'),
              style: ElevatedButton.styleFrom(
                shape: StadiumBorder(),
              ),
            ),
            SizedBox(height: 5,),
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SignUpScreen()),
                );
              },
              child: Text('SIGN UP'),
              style: ElevatedButton.styleFrom(
                shape: StadiumBorder(),
              ),
            )
          ],
        ),
      ),
    );
  }
}

那就是init它应该检查用户,如果它不为空,则推送到homepage. 但我得到了错误:

在 _MyHomePageState.initState() 完成之前调用了dependOnInheritedWidgetOfExactType<_ScaffoldMessengerScope>() 或dependOnInheritedElement()。

我想这是有道理的,因为我试图在Scaffold加载之前使用它。鉴于这一切,我如何在应用启动时检查用户登录后显示主页/登录页面?

标签: firebaseflutterdartfirebase-authentication

解决方案


我建议在小部件树中尽可能高地设置 StreamBuilder,例如在 runApp 中。它将监听任何 userChanges 并相应地重建内容。

下面的简化代码片段:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp().then((value) {
    print('firebase initialized');
  }).catchError((err) => print(err));

  runApp(GetLandingPage());
}


class GetLandingPage extends StatelessWidget {
  const GetLandingPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.userChanges(),
      initialData: FirebaseAuth.instance.currentUser,
      builder: (BuildContext context, AsyncSnapshot<User?> snapshot) {
        // Check if user is logged in
        final String? uid = snapshot.data?.uid ?? null;

        if (uid != null)
          return HomePage();

        return LoginPage();
      },
    );
  }
}

推荐阅读