【问题标题】:Firebase Android onAuthStateChanged called twiceFirebase Android onAuthStateChanged 调用了两次
【发布时间】:2016-10-07 00:24:09
【问题描述】:

我已经开始使用新的 Firebase SDK。

当我进行用户登录时,我的 onAuthStateChanged 方法被调用了两次,状态相同(等用户登录)。

我确定我只将 AuthStateListener 添加到 FirebaseAuth 参考中一次。

有什么帮助吗?

【问题讨论】:

标签: android firebase firebase-authentication


【解决方案1】:

虽然此处提供的其他答案可能会完成这项工作,但我发现管理标志很麻烦且容易出错。

我更喜欢在短时间内消除事件的抖动。假设用户在 200 毫秒内登录然后注销是非常不可能的,甚至是不可能的。

TLDR

去抖动意味着在处理事件之前,您等待查看相同的事件是否会在预定义的时间段内再次触发。 如果确实如此,则重置计时器并再次等待。 如果没有,则由您处理该事件。

这是一个 Android 问题,不是我的领域,但我确信 android 提供了某种可以帮助完成任务的工具。 如果没有,您可以使用一个简单的计时器制作一个。

以下是 Javascript 实现的样子:

var debounceTimeout;
const DebounceDueTime = 200; // 200ms

function onAuthStateChanged(auth)
{
    if (debounceTimeout)
        clearTimeout(debounceTimeout);

    debounceTimeout = setTimeout(() =>
    {
        debounceTimeout = null;

        handleAuthStateChanged(auth);
    }, DebounceDueTime);
}

function handleAuthStateChanged(auth)
{
    // ... process event
}

【讨论】:

  • 最佳解决方案恕我直言。希望我在写 if else 阶梯之前看到这个答案。哎呀。
【解决方案2】:
  try{
       FirebaseAuth.getInstance().signOut();
       FirebaseInstanceId.getInstance().deleteInstanceId();
   }catch (Exception ex){
       ex.printStackTrace();
   }

当用户从 gmail 注销时,该用户也应该从 firebase 注销。这就是我解决此问题的方法。

【讨论】:

    【解决方案3】:
    if (authStateListener == null) {
            authStateListener = new FirebaseAuth.AuthStateListener() {
                @Override
                public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                    if (firebaseAuth.getCurrentUser() == null) {
                        //Do anything here which needs to be done after signout is complete
                        FirebaseAuth.getInstance().removeAuthStateListener(this);
                        Log.d(TAG_, "logout");
    
    
                        finish();
                    } else {
                    }
                }
            };
        }
    

    应调用 FirebaseAuth.getInstance().removeAuthStateListener(this)

    【讨论】:

      【解决方案4】:

      通常我想在添加侦听器之前设置 UI,并随时重复设置身份验证状态更改(避免初始双重调用)。我的解决方案是增强布尔标志解决方案并跟踪最后一个用户的 uid(不是令牌),它可能为 null。

      private FirebaseAuth firebaseAuth;
      private String lastUid; // keeps track of login status and changes thereof
      

      onCreate 中,我获取 auth 实例并相应地设置 UI,然后在 onStart

      中添加侦听器
      @Override
      protected void onCreate(Bundle savedInstanceState){
          ...
          firebaseAuth = FirebaseAuth.getInstance();
          getUserSetUI();
          ...
      }
      

      其中 getUserSetUI 根据 auth 实例设置 lastUid

      private void getUserSetUI(){
          lastUid = (firebaseAuth == null || firebaseAuth.getCurrentUser() == null) ?
                  null : firebaseAuth.getUid();
          setUI(!(lastUid == null));
      }
      

      监听器检查状态是否真的改变了

      @Override
      public void onAuthStateChanged(@NonNull FirebaseAuth auth){
          String uid = auth.getUid(); // could be null
          if( (uid == null && lastUid != null) || // loggedout
                  (uid != null && lastUid == null) || // loggedin
                  (uid != null && lastUid != null && // switched accounts (unlikely)
                          !uid.equals(lastUid))){
              getUserSetUI();
          }
      }
      

      【讨论】:

        【解决方案5】:

        我的解决方法是使用全局声明的布尔值来标记是否需要调用 onAuthStateChanged。

        private Boolean authFlag = false;
         mAuthListener = new FirebaseAuth.AuthStateListener() {
                @Override
                public void onAuthStateChanged(@NonNull final FirebaseAuth firebaseAuth) {
                    if (firebaseAuth.getCurrentUser() != null) {
                        if(authFlag== false) {
                            // Task to perform once
                            authFlag=true;
                        }
                    }
                }
            };
        

        【讨论】:

        • 谢谢简单,但当您不想浪费更多时间时,可以完成工作。
        【解决方案6】:

        是的,这很烦人。这是由于注册电话。不仅如此,onAuthStateChanged 还会在许多不同的状态下被多次调用,不可能知道它是哪个状态。

        Documentation 说:

        onAuthStateChanged(FirebaseAuth 身份验证)

        当身份验证状态发生变化时,会在 UI 线程中调用此方法:

        • 在监听器注册之后

        • 当用户登录时

        • 当前用户退出时

        • 当当前用户改变时

        • 当当前用户的令牌发生变化时

        这里有一些发现当前状态的提示:

        • 注册调用:跳过带有标志的第一个调用。
        • 用户已登录:参数中的用户为 != null。
        • 用户已退出:参数中的用户为 == null。
        • 当前用户更改:参数中的用户为 != null 且最后一个用户 ID 为 != 参数中的用户 ID
        • 用户令牌刷新:参数中的用户为 != null 且最后一个用户 ID 为 == 参数中的用户 ID

        这个监听器很乱而且很容易出错。 Firebase 团队应该调查一下。

        【讨论】:

        • 我同意。此问题目前存在于 iOS 上。感谢您为我们整理状态。
        • 即使过了将近 5 年,问题依然存在......
        猜你喜欢
        • 2019-09-14
        • 2016-10-07
        • 1970-01-01
        • 2018-10-02
        • 2018-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多