如何避免Firebase AuthListener触发两次?

时间:2020-06-10 11:23:53

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

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

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,则只有一次。

1 个答案:

答案 0 :(得分: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");
    }
}

无论如何,如果这不是必须避免的事情,那么可以放心地忽略它,尤其是在尝试记录某些东西的情况下,但是如果要执行一些代码执行/计算,是的,会有些问题。

希望能对您的回答有所帮助,对不起。 编码愉快!