我成功实现了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,则只有一次。
答案 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");
}
}
无论如何,如果这不是必须避免的事情,那么可以放心地忽略它,尤其是在尝试记录某些东西的情况下,但是如果要执行一些代码执行/计算,是的,会有些问题。
希望能对您的回答有所帮助,对不起。 编码愉快!