在 Flutter 中使用 StreamProvider 4.0.1 从 Firebase 监控身份验证状态

Posted

技术标签:

【中文标题】在 Flutter 中使用 StreamProvider 4.0.1 从 Firebase 监控身份验证状态【英文标题】:Monitor Auth Status from Firebase using StreamProvider 4.0.1 in Flutter 【发布时间】:2020-04-29 02:52:22 【问题描述】:

如果用户没有明确退出应用程序,我会尝试自动登录。我正在使用 firebase 进行身份验证,并使用来自 pub 的提供程序包来监视身份验证状态更改。

我有一个服务 dart 文件(最初来自 TheNetNin​​ja 教程),它公开了一个流并使用流提供程序包装了 main.dart 文件。据我了解,在provider 4.0.1 中,不能再使用.value and supply the value,如下所示:

class MyApp extends StatelessWidget 
// This widget is the root of your application.
@override
Widget build(BuildContext context) 
  return StreamProvider<User>.value(
    value: AuthService().user,
     child: MaterialApp(
     debugShowCheckedModeBanner: false,
     title: 'Flutter Brewzz',
     home: Wrapper(),
   ),
  );

但要更改为此类内容,请使用create instead of value,如下所示:

class FoodMart extends StatelessWidget 
// This widget is the root of your application.
@override
Widget build(BuildContext context) 
  return StreamProvider(
    create: (_) => AuthService().user,
    child: MaterialApp(
      title: 'Flutter Demo',
      onGenerateRoute: Router.generateRoute,
      home: Landing(),
    ),
  );

我已关闭并重新打开应用程序,但仍未重定向到主页。我做错了吗? 这是AuthService.dart类的实现:

import 'dart:async';

import 'package:firebase_auth/firebase_auth.dart';
import 'package:food_mart/models/users.dart';
import 'package:food_mart/services/database.dart';

class AuthService 

FirebaseAuth _mAuth = FirebaseAuth.instance;

Stream<User> get user 
  return _mAuth.onAuthStateChanged.map(_mapUserFromFirebase);


User _mapUserFromFirebase(FirebaseUser firebaseUser) 
  return firebaseUser != null ? User(userId: firebaseUser.uid) : null;


Future createUser(String email, String pwd, String role) async
  try 
    AuthResult result = await _mAuth.createUserWithEmailAndPassword(email: email, password: pwd);
    FirebaseUser firebaseUser = result.user;

    await DatabaseService(userId: firebaseUser.uid).setUserData(email: email, role: role);
    return _mapUserFromFirebase(firebaseUser);
   catch(e)
    print(e.toString());
    return e;
  


Future loginUser(String email, String pwd) async
  try 
    AuthResult authResult = await _mAuth.signInWithEmailAndPassword(email: email, password: pwd);
    FirebaseUser firebaseUser = authResult.user;
    return _mapUserFromFirebase(firebaseUser);
   catch(e)
    print(e.toString());
    return null;
  


Future signOut() async 
  try 
    return await _mAuth.signOut();
   catch(e)
    print(e.toString());
    return null;
  



为简洁起见,User 模型已被省略。请问有什么建议吗?谢谢

【问题讨论】:

您是在本地存储上存储用户名和密码,还是本地令牌?我在你的代码中遗漏了什么吗?您希望应用如何重新对用户进行身份验证? 将 authstatechanged 方法放入流中,理想情况下(在使用颤振之前)以这种方式工作 ===> 表示登录直到退出 我无法让流读取 main.dart 中的值,可能是因为我设置错误? 但是,如果您关闭并重新打开应用程序,则存储在内存中的所有内容都会丢失。您需要获取令牌并将其存储在本地,例如 SharedPreferences。如果您需要有关如何生成令牌并将其存储在本地应用程序中的示例,我可以将其写在答案上。 Firebase 不是这样工作的,先生。您必须退出才能重定向或监控身份验证状态以保持主页打开,即绕过重新身份验证。 【参考方案1】:

我有类似的问题,但上面的代码有效。

  class Wrapper extends StatelessWidget 
  @override
  Widget build(BuildContext context) 

    final user = Provider.of<User>(context);

    if(user == null)
      return Landing();
    else
      return Index();
    
  

就像你一样,它并没有为我改变页面。原来代码一直在工作,只有我从另一个名为LoginWithEmail 的页面登录用户,该页面在Landing 类的按钮事件中被推入堆栈。登录后我刚刚在LoginWithEmail 上做了一个Navigator.pop(),发现Wrapper 类变成了Index

//code call inside login button onpressed from LoginWithEmail class
AuthService _authService = AuthService();
_authService.loginUser(email, password).then((value) 
   User user = value;
   if(user!=null)
     Navigator.pop();
   

【讨论】:

以上是关于在 Flutter 中使用 StreamProvider 4.0.1 从 Firebase 监控身份验证状态的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter Web 中使用 Flutter 移动包

如何使用 flutter_webview 插件在 Flutter 中启用位置?

在flutter中使用Chopper网络库和flutter_bloc库

Flutter : 在 Flutter web 中使用 Froala-editor

如何在flutter中使用flutter_webview_plugin和AndroidX

在 Flutter 中使用 webview_flutter 4.0 | 基础用法与事件处理