firebase - 如何确定用户在使用 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
加载之前使用它。鉴于这一切,我如何在应用启动时检查用户登录后显示主页/登录页面?
解决方案
我建议在小部件树中尽可能高地设置 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();
},
);
}
}
推荐阅读
- javascript - 如何在不同的范围内使用 DOM 引用的 .value?(重构/范围问题)
- javascript - 如何在函数中调用javascript函数
- c++11 - 如何在 C++ 的初始化列表中正确缩进 emacs?
- python - 我怎样才能弄清楚这个 Python 代码是做什么的?
- r - 绘制多个光栅图像时填充空白
- javascript - 如何为 html 元素设置不同颜色(自动突出显示)的样式
- unit-testing - Vue.js 单元测试 ErrorBoundary
- c# - 实现属性路由
- android - Android Mapbox 标记标签
- python - 将 PDF 阅读函数结果保存到变量中