如何在 Flutter 中管理 Firebase 身份验证状态? [英] How to manage Firebase Authentication state in Flutter?

查看:21
本文介绍了如何在 Flutter 中管理 Firebase 身份验证状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 WelcomeScreen,其中包含注册和登录,以及我想在用户登录后重定向的 HomeScreen.为了管理身份验证数据,我创建了一个auth.dart 带有 static 属性和方法,这样我就可以在所有页面上使用相同的数据访问它们.

import 'package:firebase_auth/firebase_auth.dart';类认证{静态最终身份验证 = FirebaseAuth.instance;静态 Future注销()异步{等待 auth.signOut();}静态 FutureloginUser(String userEmail, String userPassword) async {等待 auth.signInWithEmailAndPassword(电子邮件:userEmail,密码:userPassword);}静态 FuturegetCurrentUser() 异步 {返回等待 auth.currentUser();}}

main.dart 文件中,我使用StreamBuilder 根据更改的身份验证数据更改当前屏幕.我从


完整代码:

void main() async {WidgetsFlutterBinding.ensureInitialized();等待 Firebase.initializeApp();运行应用程序(ChangeNotifierProvider(创建:(_) =>AuthModel(),孩子:材料应用程序(主页:消费者(生成器:(_, auth, __) =>auth.isSignedIn ?主页() : 欢迎页面(),),),),);}class WelcomePage 扩展了 StatelessWidget {@覆盖小部件构建(BuildContext 上下文){返回脚手架(appBar: AppBar(title: Text('WelcomePage')),身体:中心(孩子:ElevatedButton(onPressed: () =>Navigator.push(context, MaterialPageRoute(builder: (_) => LoginPage())),child: Text('转到登录页面'),),),);}}class LoginPage 扩展了 StatelessWidget {@覆盖小部件构建(BuildContext 上下文){返回脚手架(appBar: AppBar(title: Text('登录页面')),身体:中心(孩子:ElevatedButton(onPressed: () 异步 {最终模型 = context.read();await model.signIn(email: 'test@test.com', password: 'test1234');Navigator.pop(上下文);},孩子:文本('登录'),),),);}}class HomePage 扩展了 StatelessWidget {@覆盖小部件构建(BuildContext 上下文){返回脚手架(appBar: AppBar(title: Text('HomePage')),身体:中心(孩子:FloatingActionButton.extended(onPressed: () 异步 {最终模型 = context.read();等待 model.signOut();},标签:文本('退出'),),),);}}类 AuthModel 扩展 ChangeNotifier {最终 FirebaseAuth _auth = FirebaseAuth.instance;bool get isSignedIn =>_auth.currentUser != null;未来<void>signIn({required String email, required String password}) async {等待_auth.signInWithEmailAndPassword(电子邮件:电子邮件,密码:密码);通知监听器();}未来<void>签出()异步{等待 _auth.signOut();通知监听器();}}

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?

解决方案

Null safe code (using provider)


Full code:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(
    ChangeNotifierProvider<AuthModel>(
      create: (_) => AuthModel(),
      child: MaterialApp(
        home: Consumer<AuthModel>(
          builder: (_, auth, __) => auth.isSignedIn ? HomePage() : WelcomePage(),
        ),
      ),
    ),
  );
}

class WelcomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('WelcomePage')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.push(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: ElevatedButton(
          onPressed: () async {
            final model = context.read<AuthModel>();
            await model.signIn(email: 'test@test.com', password: 'test1234');
            Navigator.pop(context);
          },
          child: Text('Login'),
        ),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('HomePage')),
      body: Center(
        child: FloatingActionButton.extended(
          onPressed: () async {
            final model = context.read<AuthModel>();
            await model.signOut();
          },
          label: Text('Log out'),
        ),
      ),
    );
  }
}

class AuthModel extends ChangeNotifier {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  bool get isSignedIn => _auth.currentUser != null;

  Future<void> signIn({required String email, required String password}) async {
    await _auth.signInWithEmailAndPassword(email: email, password: password);
    notifyListeners();
  }

  Future<void> signOut() async {
    await _auth.signOut();
    notifyListeners();
  }
}

这篇关于如何在 Flutter 中管理 Firebase 身份验证状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆