firebase - 挣扎于 Flutter 中的 authStateChanges

标签 firebase flutter dart firebase-authentication

每当用户关闭应用程序时,他们都必须重新登录。我查看并尝试实现 authStateChanges。但是我的应用程序仍然强制用户在关闭应用程序后重新登录。在 App 类中,您可以看到我尝试完全执行 authStateChange,但不幸的是,似乎什么也没发生。

Future<void> main() async {


WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(App());
}

// Firebase Auth Instance
FirebaseAuth auth = FirebaseAuth.instance;

class MyApp extends StatelessWidget {
  final Future<FirebaseApp> _initialization = Firebase.initializeApp();



// This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
  title: 'Tanbo',
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  home: LoginPage(),
);


}
}

// This is the main root screen of the Tanbo app
class App extends StatelessWidget {
  final Future<FirebaseApp> _initialization = Firebase.initializeApp();



@override
  Widget build(BuildContext context) {
    return FutureBuilder(
      // Initialize FlutterFire
      future: _initialization,
  

builder: (context, snapshot) {
    final user = FirebaseAuth.instance.authStateChanges().listen((User user) {
      if (user == null) {
        print('User signed out');
      } else {
        print('User signed in');
      }
    });

    // Check for errors
    if (snapshot.hasError) {
      return ErrorHandler();
    }

    // Once complete, show your application
    if (snapshot.connectionState == ConnectionState.done) {
      // If the user isn't logged in, we will be sent to sign up page.
      if (user != null) {
        return MyApp();
      } else {
        // If the user is logged in, TabHandler will be shown.
        return TabHandler();
      }
    }

    // Otherwise, show something whilst waiting for initialization to complete
    return LoadingHandler();
  },
);


 }
}

最佳答案

问题是您已明确将登录页面设为主页。当应用程序打开时,它会自动读取 main.dart文件并将登录页面视为分配的主页。
这就是你修复它的方法。并且还制作了一个身份验证系统,您可以在应用程序的任何位置获取登录用户的 ID。
你需要什么:

  • 任何版本的提供程序依赖项。最好是最新的
  • 一个微笑——别皱眉了。您即将解决您的问题
  • Firebase 身份验证依赖项。无论哪个版本。我会给你一个修复
    对于最新版本和明显较旧的版本。

  • 步骤 0:添加所需的依赖项并运行 flutter pub get。这一个是没有道理的。
    第一步:制作auth_services类(class):
    代码如下
    对于旧版本的 firebase auth :
    import 'package:firebase_auth/firebase_auth.dart';
    import 'package:google_sign_in/google_sign_in.dart';
    
    class AuthService {
      final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
      final GoogleSignIn _googleSignIn = GoogleSignIn();
    
      Stream<String> get onAuthStateChanged =>
          _firebaseAuth.onAuthStateChanged.map(
                (FirebaseUser user) => user?.uid,
          );
    
      // GET UID
      Future<String> getCurrentUID() async {
        return (await _firebaseAuth.currentUser()).uid;
      }
    }
    
    对于较新版本的 firebase 身份验证依赖项:
    class AuthService {
      final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
      final GoogleSignIn _googleSignIn = GoogleSignIn();
    
      Stream<User> get onAuthStateChanged => _firebaseAuth.authStateChanges();
    
      // GET UID
      Future<String> getCurrentUID() async {
        return _firebaseAuth.currentUser.uid;
      }
    }
    
    解释:我已经制作了这个类来处理所有的身份验证函数。我正在制作一个名为 onAuthStateChanged 的​​函数,它返回一个 User 类型的流(旧版本的 firebase auth 的 id),我将收听这个流以查明是否有用户登录。
    第 2 步:创建将包装整个应用程序的身份验证提供程序,并使其可以在应用程序的任何位置获取我们的用户 ID。
    创建一个名为 auth_provider.dart 的文件。
    代码如下。
    import 'package:flutter/material.dart';
    import 'auth_service.dart';
    
    class Provider extends InheritedWidget {
      final AuthService auth;
      Provider({
        Key key,
        Widget child,
        this.auth,
      }) : super(key: key, child: child);
    
      @override
      bool updateShouldNotify(InheritedWidget oldWiddget) {
        return true;
      }
    
      static Provider of(BuildContext context) =>
          (context.dependOnInheritedWidgetOfExactType<Provider>());
    }
    
    下一步是将整个应用程序包装在此提供程序小部件中,并将主 Controller 设置为主页。
    第 3 步:在 main.dart 文件或其他任何地方,创建一个名为 HomeController 的类来处理登录状态,并将 home Controller 设置为分配的主页。
    注意:我设置了一个黑色容器,在加载应用程序时显示,以确定用户是否登录。这是一个相当快的过程,但如果您愿意,您可以将其设置为应用程序主题颜色的容器。您甚至可以将其设置为启动画面。 (请注意。这个容器最多显示大约 1 秒。根据我的经验)
    代码如下:
    导入所有必要的东西
    void main() {
     //WidgetsFlutterBinding.ensureInitialized();
     // await Firebase.initializeApp();
    //only add these if you're on the latest firebase
      runApp(MyApp());
    }
    
     class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Provider(
          auth: AuthService(),
          child: MaterialApp(
                title: 'Dreamora',
                theme: ThemeData(
                  // fontFamily: "Montserrat",
                  brightness: Brightness.light,
                  inputDecorationTheme: InputDecorationTheme(
                    contentPadding:
                        EdgeInsets.only(top: 10, bottom: 10, left: 10, right: 10),
                    border: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(5.0),
                    ),
                  ),
                  primarySwatch: Colors.purple,
                  visualDensity: VisualDensity.adaptivePlatformDensity,
                ),
                home: HomeController(),
              );
            },
          ),
        ),}
    //(I think i have messed up the brackets here, but, you get the 
    //gist)
    
    class HomeController extends StatelessWidget {
      const HomeController({Key key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        final AuthService auth = Provider.of(context).auth;
    
        return StreamBuilder(
          stream: auth.onAuthStateChanged,
          builder: (context, AsyncSnapshot<String> snapshot) {
            if (snapshot.connectionState == ConnectionState.active) {
              final bool signedIn = snapshot.hasData;
              return signedIn ? DashBoard() : FirstView();
            }
            return Container(
              color: Colors.black,
            );
          },
        );
      }
    }
    
    说明:家庭 Controller 只是一个 Steam 生成器,它监听我们所做的 auth 更改。如果有任何东西,则用户已登录。如果没有,则他已注销。相当简单。尽管在确定用户的登录状态之间存在 1 秒的延迟。苏,那段时间我要退回一个黑色的容器。用户在打开应用程序后会看到屏幕变黑约一秒钟,然后出现轰鸣声。主页
    重要提示:您应该使用提供程序包装整个应用程序。这个很重要。请不要忘了。
    如何在应用程序中的任何时候获取用户 ID
    Provider.of(context).auth.getCurrentUID()
    
    你去吧。享受
    [编辑]正如 L. Gangemi 所说,新版本的 Firebase Auth 返回用户流。所以将家庭 Controller 代码编辑为
    builder: (context, AsyncSnapshot<User> snapshot) {
    

    关于firebase - 挣扎于 Flutter 中的 authStateChanges,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64520543/

    相关文章:

    android - FirebaseMessagingService.zzo 上的 NullPointerException(未知来源)

    firebase - NuxtJS 状态更改和 firebase 身份验证

    java - 如何在原始堆栈跟踪位置集中记录异常?

    flutter - 如何在flutter中使用Firebase使用电话身份验证来检查用户是否已登录?

    postgresql - 使用 dart 和 postgresql 按查询排序

    flutter - 卸载应用程序时清除共享首选项?

    android - 出现错误;没有为类型 '[]' 定义运算符 'Object? Function()'

    ios - firebase 社交登录未重定向到应用程序、ionic 3、ios

    dart - 如何在 flutter 中在按下/手指/鼠标/光标位置显示菜单

    flutter - 如何在 flutter 中制作半圆形 slider