【问题标题】:How to avoid Firebase AuthListener to be triggered twice?如何避免 Firebase AuthListener 被触发两次?
【发布时间】:2020-06-10 11:23:53
【问题描述】:

我成功实现了 Firebase 匿名身份验证和 Google。我还为用户提供了退出的可能性。我还实现了一个 FirebaseAuth.AuthStateListener,在用户状态发生变化时收到通知。如果我从谷歌退出,监听器会被调用一次。但是,当使用完全相同的代码注销匿名用户时,会调用两次侦听器。是正常行为吗?如何避免这种情况?

public class MainActivity extends AppCompatActivity implements FirebaseAuth.AuthStateListener {
    @Inject FirebaseAuth auth;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //Basic stuff
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        if (menuItem.getItemId() == R.id.nav_sign_out) {
            singOutFirebase();
        }
        return true;
    }

    private void singOutFirebase() {
        auth.signOut();
    }

    @Override
    public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
        Log.d("TAG", "onAuthStateChanged");
    }

    @Override
    protected void onStart() {
        super.onStart();
        auth.addAuthStateListener(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        auth.removeAuthStateListener(this);
    }
}

当我退出匿名帐户时,onAuthStateChanged 打印了两次。对于 Google,只有一次。

【问题讨论】:

  • 您好,我很乐意为您提供帮助,但您能出示一下代码吗?应用程序运行时的堆栈跟踪/logcat?我也许能看出什么问题。谢谢。
  • @FEBRYANASAPERDANA 我只在单击按钮时调用FirebaseAuth.getInsance().signOut(); 并在实现的onAuthStateChanged 方法中,我只有一个日志语句,在匿名身份验证的情况下被触发两次,并且只有一次在谷歌的情况下。
  • @LisDya 向我们展示代码,而不是描述它。您可以通过单击其下方的edit 链接将其添加到问题中。 “寻求调试帮助的问题('为什么这段代码不起作用?')必须包括所需的行为、特定问题或错误必要的最短代码 重现它在问题本身。没有明确的问题陈述的问题对其他读者没有用处。请参阅:How to create a Minimal, Complete, and Verifiable example."
  • @FEBRYANASAPERDANA 请检查我的代码。
  • @FrankvanPuffelen 请检查我的代码。

标签: java android firebase firebase-realtime-database firebase-authentication


【解决方案1】:

尝试在用户退出/登录时进行一些检查,然后从那里登录。您可以在 onAuthStateChanged 侦听器回调中执行这样的检查:

if (firebaseAuth.getCurrentUser() == null) {   
   Log.d("TAG", "onAuthStateChanged - User are signed out.");
} else if (firebaseAuth.getCurrentUser() != null) {
   Log.d("TAG", "onAuthStateChanged - User are signed in.");
}

虽然由于时间有限,我现在没有对其进行测试,但我认为它会起作用,因为它将自己作为网关来防止打印多个日志。如果它不起作用,您可以评论我的答案:)

在其他平台(除了Android,如React/React Native)也有其他讨论,onAuthStateChanged在使用匿名账户时会被调用两次或多次。我不确定这是否是正常行为,但我认为您的想法是正确的 - 看起来有问题,因为应该只通知侦听器一个事件 - 他们登录或退出。

您还可以检查其他代码以查看您是否正在添加其他 AuthStateListener,因为 AFAIK 以及我在此论坛和 Github 上找到的其他讨论,可能会导致冲突。

您的应用程序中是否有任何应用程序类/模块? 您可以在此处设置 AuthStateListener,并在该 Application 类中创建一个静态成员以包含您的 Application 的实例/对象,以便您可以从任何地方访问侦听器。由于您在 Application 类中设置 AuthStateListener,因此无需向任何活动/片段添加更多侦听器。只需使用全局 AuthStateListener。

无论如何,您也可以使您的 AuthStateListener 可重入/幂等。这意味着您可以跟踪/记录该值,无论是基于 Int 的计数器还是布尔值,以了解 AuthStateListener 是否已被调用,并使您能够仅侦听一个特定事件 - 登录或注销.像这样:

 private boolean hasAuthListenerBeenCalled = false
 // other code
 @Override
 public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
    if (hasAuthListenerBeenCalled) {
       // this auth state listener has already been called, ignore/omit any code 
       // execution or logging.
    } else {
       //has not been called yet, perform some code execution/logging.
       Log.d("TAG", "onAuthStateChanged");
    }
}

无论如何,如果这不是你需要避免的那么糟糕的事情,那么你可以放心地忽略它,特别是如果你试图记录一些东西,但如果你要执行一些代码执行/计算,是的,会有问题的。

希望对您有帮助,并对冗长的回答表示抱歉。 编码愉快!

【讨论】:

  • 感谢您的回答。我现在就试试你的方法,投了赞成票。
  • 祝你好运,如果您需要进一步的帮助,请随时发表评论/询问 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
  • 2020-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-16
相关资源
最近更新 更多