如何在Flutter中管理Firebase身份验证状态? [英] How to manage Firebase Authentication state in Flutter?
问题描述
我有一个 WelcomeScreen
,其中包含注册和登录以及 HomeScreen
,我想在用户之后重定向到该位置登录。为了管理身份验证数据,我创建了一个 auth.dart
,其中包含 static
属性和方法,因此我可以访问
import'package:firebase_auth / firebase_auth.dart';
class Auth {
static final auth = FirebaseAuth.instance;
静态Future< void> logout()async {
等待auth.signOut();
}
静态Future< void> loginUser(String userEmail,String userPassword)异步{
等待auth.signInWithEmailAndPassword(电子邮件:userEmail,密码:userPassword);
}
静态Future< FirebaseUser> getCurrentUser()async {
return await auth.currentUser();
}
}
在 main.dart
文件,我正在使用 StreamBuilder
根据更改身份验证数据来更改当前屏幕。我从
[我将其添加为单独的答案,因为它使用了提供程序包]
而不是使变量和 Auth
类中的方法 static
,则应使用 Provider
或其他一些型号。我在 Auth
类中使用 bool
变量来跟踪登录,您可以根据需要修改该类。
void main(){
WidgetsFlutterBinding.ensureInitialized();
runApp(
ChangeNotifierProvider< Auth>(
create:(_)=> Auth(),
子代:MaterialApp(home:MyApp()),
),
);
}
类MyApp扩展了StatelessWidget {
@override
Widget build(BuildContext context){
return Consumer< Auth>(
builder :(_,auth,__){
if(auth.loggedIn)返回HomeScreen();
返回WelcomeScreen();
},
);
}
}
类HomeScreen扩展StatelessWidget {
@override
Widget build(BuildContext context){
return Scaffold(
appBar:AppBar(标题:文本('主屏幕')),
floatActionButton:FloatingActionButton.extended(
标签:Text('登出'),
onPressed:()异步{
final auth = Provider.of< Auth>(上下文,侦听:false);
等待auth.logout();
},
),
);
}
}
类WelcomeScreen扩展了StatelessWidget {
@override
Widget build(BuildContext context){
return Scaffold(
appBar:AppBar(标题:文本('欢迎屏幕')),
正文:中心(
子对象:RaisedButton(
onPressed:()=> Navigator.pushReplacement(context,MaterialPageRoute (builder:(_)=> LoginPage())),
子级:Text('Go to Login Page'),
),
),
);
}
}
类LoginPage扩展StatelessWidget {
@override
Widget build(BuildContext context){
return Scaffold(
appBar:AppBar(标题:文本('登录页面')),
正文:Center(
子级:RaisedButton(
onPressed:()异步{
final auth =提供者.of< Auth>(上下文,监听:false);
等待auth.loginUser('test@test.com','test1234');
等待Navigator.pushReplacement(上下文,MaterialPageRoute(builder: (_)=> MyApp()));
},
子级:Text('Login'),
),
),
);
}
}
使用ChangeNotifier的Auth类{
final _auth = FirebaseAuth.instance;
bool _loggedIn = false;
bool获取登录=> _登录;
Future< void> logout()async {
await _auth.signOut();
_loggedIn = false;
notifyListeners();
}
Future< void> loginUser(String userEmail,String userPassword)async {
await _auth.signInWithEmailAndPassword(电子邮件:userEmail,密码:userPassword);
_loggedIn = true;
notifyListeners();
}
Future< FirebaseUser> getCurrentUser()async {
return wait _auth.currentUser();
}
}
现在,即使您正在登录,也可以看到从 LoginPage
进入,它不是您的消费者
的直接子代,您可以看到其登录状态更改时,仍会调用builder
。但是,当您导航到 LoginPage
时,由于小部件树显示的是 LoginPage $,因此需要弹出弹出窗口以返回上一页。仅c $ c>。在上一个示例中,我导航到
HomeScreen
,但是在此示例中,我弹出了。
I have a WelcomeScreen
which contains sign up and login and the HomeScreen
where I want to redirect after the user logs in. To manage auth data, I have created an auth.dart
with static
properties and methods so I can access them across all pages with same data.
import 'package:firebase_auth/firebase_auth.dart';
class Auth {
static final auth = FirebaseAuth.instance;
static Future<void> logout() async {
await auth.signOut();
}
static Future<void> loginUser(String userEmail, String userPassword) async {
await auth.signInWithEmailAndPassword(email: userEmail, password: userPassword);
}
static Future<FirebaseUser> getCurrentUser() async {
return await auth.currentUser();
}
}
In main.dart
file, I am using StreamBuilder
to change the current screen based on changing auth data. I got this StreamBuilder
code from this answer.
home: StreamBuilder<FirebaseUser>(
stream: Auth.auth.onAuthStateChanged,
builder: (context, snapshot) {
if (snapshot.hasData) {
return HomeScreen();
} else {
return WelcomeScreen();
}
},
),
In my login screen, I am using the below code to trigger log in:
Future<void> login() async {
...
try {
await Auth.loginUser(userEmail, userPassword);
var user = await Auth.getCurrentUser();
print(user.displayName); // This works
} catch (error) {
print(error.message);
}
}
I don't know whether the static methods I am using are the correct way to handle Firebase auth or not but it seems to work. After logging in, I am able to display the name of the logged in user but the StreamBuilder
in main.dart
is not reflecting the updated auth data, i.e not changing the page.
Is it because of static methods or something wrong in the implementation of StreamBuilder
?
[I am adding this as a separate answer because it uses provider package]
Instead of making your variables and methods static
in Auth
class, you should use Provider
or some other models. I am using a bool
variable in Auth
class to keep track of login, you can modify the class according to your needs.
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(
ChangeNotifierProvider<Auth>(
create: (_) => Auth(),
child: MaterialApp(home: MyApp()),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<Auth>(
builder: (_, auth, __) {
if (auth.loggedIn) return HomeScreen();
return WelcomeScreen();
},
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home Screen')),
floatingActionButton: FloatingActionButton.extended(
label: Text('Sign out'),
onPressed: () async {
final auth = Provider.of<Auth>(context, listen: false);
await auth.logout();
},
),
);
}
}
class WelcomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Welcome Screen')),
body: Center(
child: RaisedButton(
onPressed: () => Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => LoginPage())),
child: Text('Go to Login Page'),
),
),
);
}
}
class LoginPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Login Page')),
body: Center(
child: RaisedButton(
onPressed: () async {
final auth = Provider.of<Auth>(context, listen: false);
await auth.loginUser('test@test.com', 'test1234');
await Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => MyApp()));
},
child: Text('Login'),
),
),
);
}
}
class Auth with ChangeNotifier {
final _auth = FirebaseAuth.instance;
bool _loggedIn = false;
bool get loggedIn => _loggedIn;
Future<void> logout() async {
await _auth.signOut();
_loggedIn = false;
notifyListeners();
}
Future<void> loginUser(String userEmail, String userPassword) async {
await _auth.signInWithEmailAndPassword(email: userEmail, password: userPassword);
_loggedIn = true;
notifyListeners();
}
Future<FirebaseUser> getCurrentUser() async {
return await _auth.currentUser();
}
}
Now you can see, even when you're logging in from LoginPage
which isn't a direct child of your Consumer
, you can see its builder
is still getting called when login status changes. However, when you navigate to LoginPage
, you need to make a pop to get back to the previous page because your widget tree was displaying LoginPage
only. In my previous example I was navigating to HomeScreen
, but in this one I am popping.
这篇关于如何在Flutter中管理Firebase身份验证状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!