【问题标题】:How to Update data for FirebaseUser Stream when Email is Verified (Flutter)验证电子邮件时如何更新 FirebaseUser 流的数据 (Flutter)
【发布时间】:2020-05-08 16:17:31
【问题描述】:

我正在构建一个带有 Firebase 身份验证的颤振应用程序来处理用户。我的目标是通过允许电子邮件注册和验证来简化用户入职体验,而无需强制用户退出并再次登录以使用全部功能。在与真实用户进行测试之前,这正是我所配置的,但压倒性的反馈是它会中断,甚至可能导致用户完全放弃身份验证流程;应用程序应该只检测验证状态的这种变化,而无需注销。

我的尝试

我在 main.dart 中使用以下内容在整个应用程序中提供身份验证状态:

StreamProvider < FirebaseUser > .value( value: FirebaseAuth.instance.onAuthStateChanged, ),

我用 user1 = Provider.of&lt;FirebaseUser&gt;(context, listen: true); 在各个页面中访问不同的属性,如三元表达式中的 user1.isEmailVerified 以确定向用户显示的内容。

我知道 onAuthStateChanged 不会被调用以更改电子邮件验证,仅用于用户登录和注销,如this question 的接受答案中所述,但我仍然需要更新确定 UI 的用户值当用户验证他们的电子邮件时显示。我选择使用“完成电子邮件验证”按钮,一旦验证,它将手动触发用户配置文件的检查和重新加载新值。这是那个按钮的代码:

() async {
    // 1
    FirebaseUser user =
    await _firebaseAuth.currentUser();
    print(user.isEmailVerified); // returns false
    // 2
    await user.getIdToken();
    print(user.isEmailVerified);// returns false
    // 3
    await user.reload();
    print(user.isEmailVerified);// returns false
    //4
    user = await _firebaseAuth.currentUser(); 
    print(user.isEmailVerified);// this finally returns true
}

最终 _firebaseAuth = FirebaseAuth.instance;

我注意到调用 .currentUser() 两次(在 reload() 之前和之后)是真正为 .isEmailVerified 属性返回 true 而无需注销并重新登录的唯一方法。这是我在 @ 中找到的答案987654322@。

如果我再次按下按钮,上面的所有打印语句都会返回 true。

问题

这很好,但问题是存储 FirebaseUser 流的 user1 变量即使在此之后也不会更改或更新,因此尽管用户电子邮件经过验证,用户界面仍然保持不变。我知道这一点是因为我在代码中进行了以下检查:

print('this one is from the stream:'); print(user1.isEmailVerified);

即使在按钮函数体中,user.isEmailVerified 返回 true,它仍然返回 false。

我尝试在按钮中调用 set state,如下所示:

setState(() {user1 = user; });

但似乎 user1 的值仍然保持不变,并且仍然为 user1.isEmailVerified 返回 false,即使我试图将其设置为从按钮功能派生的新值!

这真的很令人沮丧,因为我觉得我已经很接近了,但我只是不知道如何在整个应用程序中甚至在那个屏幕上刷新 user1(firebase 用户流)的值。这应该更直接。

我注意到在验证电子邮件后按下热重载并按下上面的按钮将在整个应用程序中自动显示更新的 .isEmailVerified 值,同时在颤振上进行调试。有没有办法以编程方式触发热重载使用的相同类型的重建,这也将刷新 firebase 用户流数据,而无需注销并重新登录?也许这就是答案所在,但我不知道如何继续。

任何帮助将不胜感激。

【问题讨论】:

    标签: firebase flutter firebase-authentication


    【解决方案1】:

    我也遇到了这个问题,并在以下人员的帮助下得到了解决:

    await user.reload();
    user = await _auth.currentUser();
    user.isEmailVerified => now it is true
    

    【讨论】:

      【解决方案2】:

      你可以使用userChanges流而不是onAuthStateChanged

      提供有关所有用户更改的事件,例如何时链接、取消链接凭据以及何时更新用户配置文件。此 Stream 的目的是监听用户的实时更新,而无需手动调用 [reload]

      https://firebase.flutter.dev/docs/auth/usage/#authentication-state

      【讨论】:

        【解决方案3】:

        身份验证状态更改侦听器对我不起作用。即使在用户验证了他的电子邮件之后,字段 isEmailVerified 仍然是 false

        我的解决方法: 从假设用户离开应用程序以验证他的电子邮件(这意味着应用程序已暂停)开始,他在验证后返回应用程序(应用程序恢复)。

        我所做的是将WidgetsBinding 附加到相关的有状态小部件,如果电子邮件经过验证,我想在该小部件中显示(但可以在其他地方完成)。这包括两个步骤。

        第一步是附加绑定:

          @override
          void initState() {
            WidgetsBinding.instance.addObserver(this);
            super.initState();
          }
        
          @override
          void dispose() {
            WidgetsBinding.instance.removeObserver(this);
            super.dispose();
          }
        

        第二步是覆盖didChangeAppLifecycleState 以重新加载用户。我创建了一个函数来重新加载并设置一个新的 firebaseUser 对象

          void didChangeAppLifecycleState(AppLifecycleState state) {
            if (state == AppLifecycleState.resumed && !firebaseUser.isEmailVerified)
              refreshFirebaseUser().then((value) => setState(() {}));
            super.didChangeAppLifecycleState(state);
          }
          Future<void> refreshFirebaseUser() async {
            await firebaseUser.reload();
            firebaseUser = FirebaseAuth.instance.currentUser;
          }
        

        所以这基本上是在每次用户返回应用程序时重新加载 firebase 用户对象,而其电子邮件未经过验证。这似乎比我在 SO 中找到的最佳解决方法更干净,后者包括通过计时器设置和取消循环动作。

        【讨论】:

          【解决方案4】:

          我在试图弄清楚为什么 user.reload() 没有更新我的用户的电子邮件验证状态时遇到了您的问题。感谢您建议再次获取 currentUser,这很有效。

          为了回答您的问题,我使用 rxdart 的 BehaviorSubject 来存储我的 FirebaseUser,因此我可以使用 StreamBuilder 从应用程序中的任何位置获取用户更改的通知:

          final BehaviorSubject<FirebaseUser> firebaseUser = new BehaviorSubject<FirebaseUser>();
          userListener = FirebaseAuth.instance.onAuthStateChanged.listen((user) {
          
            if (user == null) {
              userSignedOut();
            }
            else if (currentFirebaseUser == null || user.uid != currentFirebaseUser.uid) {
              processNewUser(user);
            }
            firebaseUser.add(user);
          });
          

          【讨论】:

            【解决方案5】:

            FirebaseAuth Flutter 插件提供了一个 Stream onAuthStateChanged,这对于在用户获取更新时很有用 登录或注销,但当用户无法提供更新时 数据本身发生变化。一个常见的问题是当我们想要检测 用户刚刚验证了他的电子邮件地址,换句话说,如果 FirebaseUser.isEmailVerified 更改了它的值,因为这是更新的 服务器端,而不是推送到应用程序。

            FirebaseAuth.currentUser() 只会检测本地所做的更改 用户,但如果在服务器端进行任何更改,它不会检测到, 除非先调用 FirebaseUser.reload() 然后我们需要调用 FirebaseAuth.currentUser() 再次获取重新加载的用户,但仍然 onAuthStateChanged 不会发出此用户。

            这可以帮助您: https://pub.dev/packages/firebase_user_stream

            您将找到手动解决方案,也可以使用该软件包。

            【讨论】:

              猜你喜欢
              • 2019-12-03
              • 2020-09-20
              • 1970-01-01
              • 2021-06-24
              • 2020-07-16
              • 2021-05-13
              • 2022-01-11
              • 2020-12-12
              相关资源
              最近更新 更多