使用 onAuthStateChanged 使用 Flutter 登录 Firebase [英] Firebase Login with Flutter using onAuthStateChanged

查看:18
本文介绍了使用 onAuthStateChanged 使用 Flutter 登录 Firebase的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Flutter 之外,当我实现 firebase 身份验证时,我总是使用 firebase 提供的 onAuthStateChanged 侦听器来确定用户是否已登录并做出相应的响应.

Outside of Flutter, when I implement firebase authentication I always use the onAuthStateChanged listener provided by firebase to determine if the user is logged in or not and respond accordingly.

我正在尝试使用 flutter 做类似的事情,但我可以找到一种方法来访问 Firebase 的 onAuthStateChanged.我正在使用 firebase_auth 和 google_signin Flutter 插件.我正在处理 firebase_auth Flutter 插件中包含的示例代码.下面是示例代码.我可以用google sign in 登录成功,但是例子太简单了,因为我想有一个观察者/监听器来检测用户的登录/退出状态.

I am trying to do something similar using flutter, but I can find a way to access onAuthStateChanged of Firebase. I am using the firebase_auth, and google_signin Flutter plugins. I am working of example code that is included with the firebase_auth Flutter plugin. Below is the sample code. I can login successfully with google sign in, but the example is too simple, because I want to have an observer/listener to detect the user's signed in/out state.

有没有办法通过观察者/侦听器使用 firebase_auth/google_signin flutter 插件进行检测以确定用户的状态?

Is there a way to detect via observer/listener using the firebase_auth/google_signin flutter plugins to determine the status of a user?

最终我希望应用程序确定用户是否登录(是/否).如果不是,则显示登录屏幕,如果是,则显示我的主应用页面.

Ultimately I want the app to determine if the user is logged in (yes/no). If not then show a login screen, if yes then show my main app page.

import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = new GoogleSignIn();

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Firebase Auth Demo',
      home: new MyHomePage(title: 'Firebase Auth Demo'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  Future<String> _message = new Future<String>.value('');

  Future<String> _testSignInAnonymously() async {
    final FirebaseUser user = await _auth.signInAnonymously();
    assert(user != null);
    assert(user == _auth.currentUser);
    assert(user.isAnonymous);
    assert(!user.isEmailVerified);
    assert(await user.getToken() != null);
    if (Platform.isIOS) {
      // Anonymous auth doesn't show up as a provider on iOS
      assert(user.providerData.isEmpty);
    } else if (Platform.isAndroid) {
      // Anonymous auth does show up as a provider on Android
      assert(user.providerData.length == 1);
      assert(user.providerData[0].providerId == 'firebase');
      assert(user.providerData[0].uid != null);
      assert(user.providerData[0].displayName == null);
      assert(user.providerData[0].photoUrl == null);
      assert(user.providerData[0].email == null);
    }
    return 'signInAnonymously succeeded: $user';
  }

  Future<String> _testSignInWithGoogle() async {
    final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
    final GoogleSignInAuthentication googleAuth =
        await googleUser.authentication;
    final FirebaseUser user = await _auth.signInWithGoogle(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );
    assert(user.email != null);
    assert(user.displayName != null);
    assert(!user.isAnonymous);
    assert(await user.getToken() != null);
    return 'signInWithGoogle succeeded: $user';
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          new MaterialButton(
              child: const Text('Test signInAnonymously'),
              onPressed: () {
                setState(() {
                  _message = _testSignInAnonymously();
                });
              }),
          new MaterialButton(
              child: const Text('Test signInWithGoogle'),
              onPressed: () {
                setState(() {
                  _message = _testSignInWithGoogle();
                });
              }),
          new FutureBuilder<String>(
              future: _message,
              builder: (_, AsyncSnapshot<String> snapshot) {
                return new Text(snapshot.data ?? '',
                    style: const TextStyle(
                        color: const Color.fromARGB(255, 0, 155, 0)));
              }),
        ],
      ),
    );
  }
}

以下是相关 flutter 包的链接:https://github.com/flutter/plugins/tree/master/packages/firebase_authhttps://github.com/flutter/plugins/tree/master/packages/google_sign_in

Here are links to the flutter packages in question: https://github.com/flutter/plugins/tree/master/packages/firebase_auth https://github.com/flutter/plugins/tree/master/packages/google_sign_in

推荐答案

我知道这个问题已经很老了,但如果有人仍在寻找它,这里是答案.

I know this question is pretty old, but here is the answer if anybody is still looking for it.

Firebase 返回 FirebaseUserStream 及其 onAuthStateChanged 函数.监听用户认证状态变化的方法有很多种.我是这样做的:

Firebase returns a Stream of FirebaseUser with it's onAuthStateChanged function. There are many ways to listen to the user's authentication state change. This is how I do it:

我将 StreamBuilder 返回到我的应用主页,StreamBuilder 根据用户的身份验证状态返回特定页面.

I return a StreamBuilder to my App's home page, and the StreamBuilder returns specific pages based on the auth status of the user.

@override
Widget build(BuildContext context) {
  return MaterialApp(
      title: 'Your App Name',
      home: _getLandingPage()
  );
}

Widget _getLandingPage() {
  return StreamBuilder<FirebaseUser>(
    stream: FirebaseAuth.instance.onAuthStateChanged,
    builder: (BuildContext context, snapshot) {
      if (snapshot.hasData) {
        if (snapshot.data.providerData.length == 1) { // logged in using email and password
          return snapshot.data.isEmailVerified
              ? MainPage()
              : VerifyEmailPage(user: snapshot.data);
        } else { // logged in using other providers
          return MainPage();
        }
      } else {
        return LoginPage();
      }
    },
  );
}

解决方案 2

您也可以在应用的 initState() 函数中创建侦听器.在注册侦听器之前,请确保 Firebase 应用已初始化.

Solution 2

You can create a listener in your app's initState() function as well. Make sure the firebase app has been initialized before registering the listener.

@override
void initState() {
  super.initState();

  FirebaseAuth.instance.authStateChanges().listen((firebaseUser) {
    // do whatever you want based on the firebaseUser state
  });
}

解决方案 3(2021 年 5 月更新)

一种不使用提供程序包的具有空安全性的简单方法:

Solution 3 (Update May 2021)

A simple approach with null-safety without using the provider package:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(App());
}

class App extends StatefulWidget {
  @override
  _AppState createState() => _AppState();
}

/// State is persistent and not rebuilt, therefore [Future] is only created once.
/// If [StatelessWidget] is used, in the event where [App] is rebuilt, that
/// would re-initialize FlutterFire and makes our app re-enter the
/// loading state, which is undesired.
class _AppState extends State<App> {
  final Future<FirebaseApp> _initFirebaseSdk = Firebase.initializeApp();
  final _navigatorKey = new GlobalKey<NavigatorState>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      navigatorKey: _navigatorKey,
      theme: theme(),
      home: FutureBuilder(
          future: _initFirebaseSdk,
          builder: (_, snapshot) {
            if (snapshot.hasError) return ErrorScreen();

            if (snapshot.connectionState == ConnectionState.done) {
              // Assign listener after the SDK is initialized successfully
              FirebaseAuth.instance.authStateChanges().listen((User? user) {
                if (user == null)
                  _navigatorKey.currentState!
                      .pushReplacementNamed(LoginScreen.routeName);
                else
                  _navigatorKey.currentState!
                      .pushReplacementNamed(HomeScreen.routeName);
              });
            }

            return LoadingScreen();
          }),
      routes: routes,
    );
  }
}

此方法可确保您仅在 SDK 完成初始化后使用 Firebase 身份验证 FirebaseAuth.instance.authStateChanges().listen().auth 更改侦听器将在应用启动时首先调用,然后在注销和登录后再次自动调用.

This approach guarantees that you only use Firebase authentication FirebaseAuth.instance.authStateChanges().listen() after the SDK completes initialization. The auth change listener will be first invoked on app launch and then automatically called again after logout and login.

.pushReplacementNamed() 将移动到新屏幕而不返回(应用栏上没有返回图标)

.pushReplacementNamed() will move to a new screen without back (no back icon on the app bar)

这篇关于使用 onAuthStateChanged 使用 Flutter 登录 Firebase的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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